package com.lanchetech.service.impl;


import com.alibaba.excel.util.CollectionUtils;
import com.baidu.fsg.uid.UidGenerator;
import com.lanchetech.bean.vo.IdentitySimpleVO;
import com.lanchetech.bean.vo.OrderSkuVO;
import com.lanchetech.common.enums.*;
import com.lanchetech.dao.*;
import com.lanchetech.entity.*;
import com.lanchetech.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.lanchetech.common.constants.JypConstant.DIRECTOR_COUNT;
import static com.lanchetech.common.constants.JypConstant.HIPO_USER_ID;

@Service
public class CommissionServiceImpl implements CommissionService {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    UserMapper userMapper;

    @Autowired
    UserCommissionMapper userCommissionMapper;

    @Autowired
    UserRelationshipMapper userRelationshipMapper;

    @Autowired
    PrivilegeMapper privilegeMapper;

    @Autowired
    SpuCommissionMapper spuCommissionMapper;

    @Autowired
    SkuCommissionMapper skuCommissionMapper;

    @Autowired
    CoinFlowMapper coinFlowMapper;

    @Autowired
    BalanceFlowMapper balanceFlowMapper;

    @Autowired
    ShopMapper shopMapper;

    @Autowired
    CommissionRecordMapper commissionRecordMapper;

    @Autowired
    SmsService smsService;

    @Autowired
    UserGroupMapper userGroupMapper;

    @Autowired
    IdentityMapper identityMapper;

    @Autowired
    CardFlowMapper cardFlowMapper;

    @Autowired
    BonusCountMapper bonusCountMapper;

    @Autowired
    RewardQueueMapper rewardQueueMapper;

    @Autowired
    AdFlowMapper adFlowMapper;

    @Autowired
    PerformanceMapper performanceMapper;

    @Autowired
    OrderAddressMapper orderAddressMapper;

    @Autowired
    UserAgentLevelMapper userAgentLevelMapper;

    @Autowired
    SpuCourierAmountMapper spuCourierAmountMapper;

    @Autowired
    HipoConfigMapper hipoConfigMapper;

    @Autowired
    DaoService daoService;

    @Autowired
    SpuMapper spuMapper;

    @Autowired
    LevelService levelService;

    @Autowired
    AgentCommissionMapper agentCommissionMapper;

    @Autowired
    CommonFarmService commonFarmService;

    @Autowired
    SkuMapper skuMapper;

    @Autowired
    UserInfoMapper userInfoMapper;

    @Autowired
    AreaPartnerMapper areaPartnerMapper;

    @Autowired
    QuartzService quartzService;

    @Autowired
    TenantMapper tenantMapper;

    @Autowired
    TenantFlowMapper tenantFlowMapper;

    @Autowired
    BossIdentityMapper bossIdentityMapper;

    @Autowired
    BossInviteShopMapper bossInviteShopMapper;

    @Autowired
    BossMapper bossMapper;

    @Autowired
    OrdersMapper ordersMapper;

    @Autowired
    PerformanceAmountMapper performanceAmountMapper;

    @Autowired
    InviteFirstBuyMapper inviteFirstBuyMapper;

    @Autowired
    GiveMemberRecordMapper giveMemberRecordMapper;

    @Autowired
    OrderDiscountMapper orderDiscountMapper;

    @Autowired
    CouponMapper couponMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    DividendPrecipitationMapper dividendPrecipitationMapper;

    @Autowired
    GroupsPerformanceMapper groupsPerformanceMapper;

    @Autowired
    ShareholderPerformanceMapper shareholderPerformanceMapper;

    @Autowired
    OrderSkuMapper orderSkuMapper;

    @Autowired
    WelfareFlowMapper welfareFlowMapper;

    @Autowired
    FinanceService financeService;

    @Resource
    UidGenerator uidGenerator;

    @Autowired
    CommonOrderService commonOrderService;

    private Map<String, String> hipoConfig;


    /**
     * 管理后台发放身份时，给相应的分红和奖励
     *
     * @param user
     * @param identityType
     */
    @Override
    public void prepareIdentityCommission(User user, IdentityTypeEnum identityType) {
        List<UserCommission> commissions = new ArrayList<>();
        Map<String, String> config = daoService.getHipoConfigMap();
        // 设置冻结时间
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 7);
        // 会员分红
        if (identityType.getType().equals(IdentityTypeEnum.MEMBER.getType())) {
//            issueMemberDividends(commissions, user.getId(), daoService.getHipoConfigNumber(HipoConfigEnum.MEMBER_PRICE.getConfig()), calendar, null, "会员分红", config);
            editDividendPrecipitation(IdentityTypeEnum.MEMBER.getType(), daoService.getHipoConfigNumber(HipoConfigEnum.MEMBER_PRICE.getConfig()), 1, config);
        }
        // 合伙人分红
        if (identityType.getType().equals(IdentityTypeEnum.PARTNER.getType())) {
            // 卖出1个合伙人，视为销售出3套799，给出对应的分红
            editDividendPrecipitation(IdentityTypeEnum.MEMBER.getType(), daoService.getHipoConfigNumber(HipoConfigEnum.PARTNER_PRICE.getConfig()), 1, config);
        }
        // 卖出1个运营中心，视为销售出10套799，给出对应的分红
        if (identityType.getType().equals(IdentityTypeEnum.SHAREHOLDER.getType())) {
            // 卖出1个运营中心，视为销售出6套799，给出对应的分红
            editDividendPrecipitation(IdentityTypeEnum.MEMBER.getType(), daoService.getHipoConfigNumber(HipoConfigEnum.SHAREHOLDER_PRICE.getConfig()), 1, config);
        }
        if (!commissions.isEmpty()) {
            userCommissionMapper.batchInsert(commissions);
        }
    }

    /**
     * 发放会员分红
     */
    @Override
    public List<UserCommission> issueMemberDividends(List<UserCommission> commissions, Long userId, BigDecimal amount, Calendar calendar, Long orderSkuId, String remark, Map<String, String> config) {


        Date date = new Date();
        // 获取所有的主管、经理、总监（仅主管以上有业绩分红）
        List<IdentitySimpleVO> identityList = identityMapper.findAllMemberForDividends(date);
        List<IdentitySimpleVO> identityListOverLevel34 = new ArrayList<>();
        List<IdentitySimpleVO> identityListOverLevel4 = new ArrayList<>();

        identityList.stream().forEach(i -> {
            if (UserLevelEnum.MEMBER_L3.getLevel().equals(i.getMemberLevel())) {
                if (i.getL3EffectTime() != null && i.getL3EffectTime().before(date)) {
                    identityListOverLevel34.add(i);
                }
            }
            if (UserLevelEnum.MEMBER_L4.getLevel().equals(i.getMemberLevel())) {
                if (i.getL4EffectTime() != null && i.getL4EffectTime().before(date)) {
                    identityListOverLevel4.add(i);
                }
                if (i.getL3EffectTime() != null && i.getL3EffectTime().before(date)) {
                    identityListOverLevel34.add(i);
                }
            }
        });

        if (!identityList.isEmpty()) {
            // 业绩分红
            BigDecimal one = amount
                    .multiply(new BigDecimal(config.get(HipoConfigEnum.MEMBER_DIVIDENDS_1_RATE.getConfig())))
                    .divide(new BigDecimal(identityList.size()), 2, BigDecimal.ROUND_HALF_UP)
                    .setScale(2, BigDecimal.ROUND_HALF_UP);

            BigDecimal two = identityListOverLevel34.isEmpty() ? BigDecimal.ZERO : amount
                    .multiply(new BigDecimal(config.get(HipoConfigEnum.MEMBER_DIVIDENDS_2_RATE.getConfig())))
                    .divide(new BigDecimal(identityListOverLevel34.size()), 2, BigDecimal.ROUND_HALF_UP)
                    .setScale(2, BigDecimal.ROUND_HALF_UP);


            BigDecimal three = identityListOverLevel4.isEmpty() ? BigDecimal.ZERO : amount
                    .multiply(new BigDecimal(config.get(HipoConfigEnum.MEMBER_DIVIDENDS_3_RATE.getConfig())))
                    .divide(new BigDecimal(identityListOverLevel4.size()), 2, BigDecimal.ROUND_HALF_UP)
                    .setScale(2, BigDecimal.ROUND_HALF_UP);


            //主管分红生效
            identityList.stream().forEach(each -> {
                // 下面所有佣金都立即发放
                // 所有主管以上可得
                if (each.getMemberLevel() >= UserLevelEnum.MEMBER_L2.getLevel()) {
                    commissions.add(buildIssued(each.getUserId(), userId, one, UserCommissionTypeEnum.MEMBER_L2_DIVIDENDS, amount, IdentityTypeEnum.MEMBER.getType(), orderSkuId, remark));
                }
            });

            //经理分红生效
            identityListOverLevel34.stream().forEach(each -> {
                // 所有经理以上可得
                if (each.getMemberLevel() >= UserLevelEnum.MEMBER_L3.getLevel()) {
                    commissions.add(buildIssued(each.getUserId(), userId, two, UserCommissionTypeEnum.MEMBER_L3_DIVIDENDS, amount, IdentityTypeEnum.MEMBER.getType(), orderSkuId, remark));
                }

            });

            identityListOverLevel4.stream().forEach(each -> {
                // 所有总监可得
                if (each.getMemberLevel() == UserLevelEnum.MEMBER_L4.getLevel()) {
                    commissions.add(buildIssued(each.getUserId(), userId, three, UserCommissionTypeEnum.MEMBER_L4_DIVIDENDS, amount, IdentityTypeEnum.MEMBER.getType(), orderSkuId, remark));
                }
            });
        }

        return commissions;
    }


    /**
     * 发放合伙人分红
     */
    @Override
    public List<UserCommission> issuePartnerDividends(List<UserCommission> commissions, Long userId, BigDecimal amount, Calendar calendar, Long orderSkuId, String remark, Map<String, String> config) {

        // 获取所有的主管、总裁、董事（仅主管以上有业绩分红）
        List<IdentitySimpleVO> identityList = identityMapper.findAllPartnerForDividends(new Date());
        List<IdentitySimpleVO> identityListOverLevel34 = new ArrayList<>();
        List<IdentitySimpleVO> identityListOverLevel4 = new ArrayList<>();

        identityList.stream().forEach(i -> {
            if (UserLevelEnum.PARTNER_L3.getLevel().equals(i.getPartnerLevel())) {
                identityListOverLevel34.add(i);
            }
            if (UserLevelEnum.PARTNER_L4.getLevel().equals(i.getPartnerLevel())) {
                identityListOverLevel34.add(i);
                identityListOverLevel4.add(i);
            }
        });

        if (!identityList.isEmpty()) {
            // 业绩分红
            BigDecimal one = amount
                    .multiply(new BigDecimal(config.get(HipoConfigEnum.PARTNER_DIVIDENDS_1_RATE.getConfig())))
                    .divide(new BigDecimal(identityList.size()), 2, BigDecimal.ROUND_HALF_UP)
                    .setScale(2, BigDecimal.ROUND_HALF_UP);

            BigDecimal two = identityListOverLevel34.isEmpty() ? BigDecimal.ZERO : amount
                    .multiply(new BigDecimal(config.get(HipoConfigEnum.PARTNER_DIVIDENDS_2_RATE.getConfig())))
                    .divide(new BigDecimal(identityListOverLevel34.size()), 2, BigDecimal.ROUND_HALF_UP)
                    .setScale(2, BigDecimal.ROUND_HALF_UP);


            BigDecimal three = identityListOverLevel4.isEmpty() ? BigDecimal.ZERO : amount
                    .multiply(new BigDecimal(config.get(HipoConfigEnum.PARTNER_DIVIDENDS_3_RATE.getConfig())))
                    .divide(new BigDecimal(identityListOverLevel4.size()), 2, BigDecimal.ROUND_HALF_UP)
                    .setScale(2, BigDecimal.ROUND_HALF_UP);


            identityList.stream().forEach(each -> {
                if (each.getPartnerLevel() >= UserLevelEnum.PARTNER_L2.getLevel()) {
                    commissions.add(build(each.getUserId(), userId, one, UserCommissionTypeEnum.PARTNER_L2_DIVIDENDS, calendar, amount, IdentityTypeEnum.PARTNER.getType(), orderSkuId, remark));
                }
                if (each.getPartnerLevel() >= UserLevelEnum.PARTNER_L3.getLevel()) {
                    commissions.add(build(each.getUserId(), userId, two, UserCommissionTypeEnum.PARTNER_L3_DIVIDENDS, calendar, amount, IdentityTypeEnum.PARTNER.getType(), orderSkuId, remark));
                }
                if (each.getPartnerLevel() == UserLevelEnum.PARTNER_L4.getLevel()) {
                    commissions.add(build(each.getUserId(), userId, three, UserCommissionTypeEnum.PARTNER_L4_DIVIDENDS, calendar, amount, IdentityTypeEnum.PARTNER.getType(), orderSkuId, remark));
                }
            });
        }

        return commissions;
    }

    /**
     * 发放运营中心分红
     */
    @Override
    public List<UserCommission> issueShareholderDividends(List<UserCommission> commissions, Long userId, BigDecimal amount, Calendar calendar, Long orderSkuId, String remark, Map<String, String> config) {

        // 获取所有的副总裁、总裁、董事（仅副总裁以上有业绩分红）
        List<IdentitySimpleVO> identityList = identityMapper.findAllShareholderForDividends();
        List<IdentitySimpleVO> identityListOverLevel34 = new ArrayList<>();
        List<IdentitySimpleVO> identityListOverLevel4 = new ArrayList<>();

        identityList.stream().forEach(i -> {
            if (UserLevelEnum.SHAREHOLDER_L3.getLevel().equals(i.getShareholderLevel())) {
                identityListOverLevel34.add(i);
            }
            if (UserLevelEnum.SHAREHOLDER_L4.getLevel().equals(i.getShareholderLevel())) {
                identityListOverLevel34.add(i);
                identityListOverLevel4.add(i);
            }
        });

        if (!identityList.isEmpty()) {
            // 业绩分红
            BigDecimal one = amount
                    .multiply(new BigDecimal(config.get(HipoConfigEnum.SHAREHOLDER_DIVIDENDS_1_RATE.getConfig())))
                    .divide(new BigDecimal(identityList.size()), 2, BigDecimal.ROUND_HALF_UP)
                    .setScale(2, BigDecimal.ROUND_HALF_UP);

            BigDecimal two = identityListOverLevel34.isEmpty() ? BigDecimal.ZERO : amount
                    .multiply(new BigDecimal(config.get(HipoConfigEnum.SHAREHOLDER_DIVIDENDS_2_RATE.getConfig())))
                    .divide(new BigDecimal(identityListOverLevel34.size()), 2, BigDecimal.ROUND_HALF_UP)
                    .setScale(2, BigDecimal.ROUND_HALF_UP);


            BigDecimal three = identityListOverLevel4.isEmpty() ? BigDecimal.ZERO : amount
                    .multiply(new BigDecimal(config.get(HipoConfigEnum.SHAREHOLDER_DIVIDENDS_3_RATE.getConfig())))
                    .divide(new BigDecimal(identityListOverLevel4.size()), 2, BigDecimal.ROUND_HALF_UP)
                    .setScale(2, BigDecimal.ROUND_HALF_UP);

            identityList.stream().forEach(each -> {
                if (each.getShareholderLevel() >= UserLevelEnum.SHAREHOLDER_L2.getLevel()) {
                    commissions.add(build(each.getUserId(), userId, one, UserCommissionTypeEnum.SHAREHOLDER_L2_DIVIDENDS, calendar, amount, IdentityTypeEnum.SHAREHOLDER.getType(), orderSkuId, remark));
                }
                if (each.getShareholderLevel() >= UserLevelEnum.SHAREHOLDER_L3.getLevel()) {
                    commissions.add(build(each.getUserId(), userId, two, UserCommissionTypeEnum.SHAREHOLDER_L3_DIVIDENDS, calendar, amount, IdentityTypeEnum.SHAREHOLDER.getType(), orderSkuId, remark));
                }
                if (each.getShareholderLevel() == UserLevelEnum.SHAREHOLDER_L4.getLevel()) {
                    commissions.add(build(each.getUserId(), userId, three, UserCommissionTypeEnum.SHAREHOLDER_L4_DIVIDENDS, calendar, amount, IdentityTypeEnum.SHAREHOLDER.getType(), orderSkuId, remark));
                }
            });
        }

        return commissions;
    }

    /**
     * 合伙人收入提点
     */
    private void incomePartnerCommission(Long subordinateId, BigDecimal amount, BigDecimal commission, Calendar calendar, List<UserCommission> commissions, Long orderSkuId, String remark) {
        UserRelationship ship = userRelationshipMapper.findOneBySubordinateId(subordinateId);
        if (ship != null && ship.getStatus().equals(RelationshipStatusEnum.BIND.getStatus())) {
            // 只有合伙人享受收入提点
            if (IdentityTypeEnum.PARTNER.getType().equals(ship.getType())) {
                commissions.add(build(ship.getSuperiorId(), subordinateId, commission, UserCommissionTypeEnum.PARTNER_GROUP_COMMISSION, calendar, amount, ship.getType(), orderSkuId, remark));

                // 登记团队业绩
                UserGroup shareholder = userGroupMapper.findOneByCaptainIdAndMemberId(ship.getSuperiorId(), ship.getSubordinateId());
                if (shareholder != null) {
                    shareholder.setOrderCount(shareholder.getOrderCount() + 1);
                    shareholder.setAmount(shareholder.getAmount().add(amount));
                    shareholder.setCommission(shareholder.getCommission().add(commission));
                    userGroupMapper.updateByPrimaryKeySelective(shareholder);
                }
            }
        }
    }

    /**
     * 运营中心收入提点
     */
    private void incomeShareholderCommission(Long subordinateId, BigDecimal amount, BigDecimal commission, Calendar calendar, List<UserCommission> commissions, Long orderSkuId, String remark) {
        UserRelationship ship = userRelationshipMapper.findOneBySubordinateId(subordinateId);
        if (ship != null && ship.getStatus().equals(RelationshipStatusEnum.BIND.getStatus())) {
            // 只有董事享受收入提点
            if (IdentityTypeEnum.SHAREHOLDER.getType().equals(ship.getType())) {
                commissions.add(build(ship.getSuperiorId(), subordinateId, commission, UserCommissionTypeEnum.SHAREHOLDER_GROUP_COMMISSION, calendar, amount, ship.getType(), orderSkuId, remark));

                // 登记团队业绩
                UserGroup shareholder = userGroupMapper.findOneByCaptainIdAndMemberId(ship.getSuperiorId(), ship.getSubordinateId());
                if (shareholder != null) {
                    shareholder.setOrderCount(shareholder.getOrderCount() + 1);
                    shareholder.setAmount(shareholder.getAmount().add(amount));
                    shareholder.setCommission(shareholder.getCommission().add(commission));
                    userGroupMapper.updateByPrimaryKeySelective(shareholder);
                }
            }
        }
    }

    private UserCommission build(Long superiorId, Long subordinateId, BigDecimal amount, UserCommissionTypeEnum typeEnum, Calendar calendar, BigDecimal performance, Byte identityType) {
        // 记录团队业绩
        UserGroup userGroup = userGroupMapper.findOneByCaptainIdAndMemberId(superiorId, subordinateId);
        if (userGroup != null) {
            userGroup.setOrderCount(userGroup.getOrderCount() + 1);
            userGroup.setAmount(userGroup.getAmount().add(performance));
            userGroup.setCommission(userGroup.getCommission().add(amount));
            userGroupMapper.updateByPrimaryKeySelective(userGroup);
        }

        return UserCommission.builder()
                .superiorId(superiorId)
                .subordinateId(subordinateId)
                .commission(amount)
                .type(typeEnum.getType())
                .freezeTime(calendar.getTime())
                .status(UserCommissionStatusEnum.FREEZE.getStatus())
                .createdAt(new Date())
                .updatedAt(new Date())
                .amount(performance)
                .identityType(identityType)
                .businessType(UserCommissionBusinessTypeEnum.USER.getType())
                .build();
    }

    private UserCommission buildIssued(Long superiorId, Long subordinateId, BigDecimal amount, UserCommissionTypeEnum typeEnum, BigDecimal performance, Byte identityType, Long orderSkuId, String remark) {

        // 记录团队业绩
        UserGroup userGroup = userGroupMapper.findOneByCaptainIdAndMemberId(superiorId, subordinateId);
        if (userGroup != null) {
            userGroup.setOrderCount(userGroup.getOrderCount() + 1);
            userGroup.setAmount(userGroup.getAmount().add(performance));
            userGroup.setCommission(userGroup.getCommission().add(amount));
            userGroupMapper.updateByPrimaryKeySelective(userGroup);
        }

        // 2、发放佣金
        userMapper.changePointById(amount, superiorId);

        // 3、创建资金流水记录
        User superior = userMapper.selectByPrimaryKey(superiorId);
        balanceFlowMapper.insert(BalanceFlow.builder()
                .userId(superiorId)
                .amount(amount)
                .tradeType(TradeTypeEnum.getByTradeType(typeEnum.getType()).getTradeType())
                .type(TradeTypeEnum.getByTradeType(typeEnum.getType()).getType())
                .point(superior.getPoint())
                .relateId(orderSkuId)
                .remark(remark)
                .createdAt(new Date())
                .build());

        return UserCommission.builder()
                .superiorId(superiorId)
                .subordinateId(subordinateId)
                .commission(amount)
                .type(typeEnum.getType())
                .freezeTime(new Date())
                .status(UserCommissionStatusEnum.ISSUED.getStatus())
                .createdAt(new Date())
                .updatedAt(new Date())
                .amount(performance)
                .identityType(identityType)
                .businessType(UserCommissionBusinessTypeEnum.USER.getType())
                .orderSkuId(orderSkuId)
                .remark(remark)
                .build();
    }

    private UserCommission buildRewardQueueIssued(Long superiorId,
                                                  Long subordinateId,
                                                  BigDecimal amount,
                                                  UserCommissionTypeEnum typeEnum,
                                                  BigDecimal performance,
                                                  Byte identityType,
                                                  Long orderSkuId,
                                                  String remark,
                                                  Long supId) {
        // 2、发放佣金
        userMapper.changePointById(amount, superiorId);

        // 3、创建资金流水记录
        User superior = userMapper.selectByPrimaryKey(superiorId);
        balanceFlowMapper.insert(BalanceFlow.builder()
                .userId(superiorId)
                .amount(amount)
                .tradeType(TradeTypeEnum.getByTradeType(typeEnum.getType()).getTradeType())
                .type(TradeTypeEnum.getByTradeType(typeEnum.getType()).getType())
                .point(superior.getPoint())
                .relateId(orderSkuId)
                .remark(remark)
                .createdAt(new Date())
                .build());

        return UserCommission.builder()
                .superiorId(superiorId)
                .subordinateId(subordinateId)
                .commission(amount)
                .type(typeEnum.getType())
                .freezeTime(new Date())
                .status(UserCommissionStatusEnum.ISSUED.getStatus())
                .createdAt(new Date())
                .updatedAt(new Date())
                .amount(performance)
                .identityType(identityType)
                .businessType(UserCommissionBusinessTypeEnum.USER.getType())
                .orderSkuId(orderSkuId)
                .remark(remark)
                .relateId(supId)
                .build();
    }

    private UserCommission build(Long superiorId, Long subordinateId, BigDecimal amount, UserCommissionTypeEnum typeEnum, Calendar calendar, BigDecimal performance, Byte identityType, Long orderSkuId, String remark) {
        return build(superiorId, subordinateId, amount, typeEnum, calendar, performance, identityType, orderSkuId, remark, null);
    }


    private UserCommission build(Long superiorId, Long subordinateId, BigDecimal amount, UserCommissionTypeEnum typeEnum, Calendar calendar, BigDecimal performance, Byte identityType, Long orderSkuId, String remark, Byte fromType) {

        // 记录团队业绩
        UserGroup userGroup = userGroupMapper.findOneByCaptainIdAndMemberId(superiorId, subordinateId);
        if (userGroup != null) {
            userGroup.setOrderCount(userGroup.getOrderCount() + 1);
            userGroup.setAmount(userGroup.getAmount().add(performance));
            userGroup.setCommission(userGroup.getCommission().add(amount));
            userGroupMapper.updateByPrimaryKeySelective(userGroup);
        }

        return UserCommission.builder()
                .superiorId(superiorId)
                .subordinateId(subordinateId)
                .commission(amount)
                .type(typeEnum.getType())
                .freezeTime(calendar.getTime())
                .status(UserCommissionStatusEnum.FREEZE.getStatus())
                .createdAt(new Date())
                .updatedAt(new Date())
                .amount(performance)
                .identityType(identityType)
                .businessType(UserCommissionBusinessTypeEnum.USER.getType())
                .orderSkuId(orderSkuId)
                .remark(remark)
                .build();
    }

    @Override
    public void issueUserCommission(UserCommission userCommission) {
        //fixme 自动收货处理解冻时 可能存在用户同时手动确认 发放两笔佣金
        // 1、先将状态变成已经发放
        userCommissionMapper.updateStatusAndUpdatedAtById(UserCommissionStatusEnum.ISSUED.getStatus(), new Date(), userCommission.getId());

        // 2、发放佣金
        userMapper.changePointById(userCommission.getCommission(), userCommission.getSuperiorId());

        // 3、创建资金流水记录
        User superior = userMapper.selectByPrimaryKey(userCommission.getSuperiorId());
        balanceFlowMapper.insert(BalanceFlow.builder()
                .userId(userCommission.getSuperiorId())
                .amount(userCommission.getCommission())
                .tradeType(TradeTypeEnum.getByTradeType(userCommission.getType()).getTradeType())
                .type(TradeTypeEnum.getByTradeType(userCommission.getType()).getType())
                .point(superior.getPoint())
                .relateId(userCommission.getId())
                .remark(userCommission.getRemark())
                .createdAt(new Date())
                .build());
    }

    @Override
    public void createVipRewardQueue(User user, Spu spu, BigDecimal amount) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 7);
        String period = daoService.getHipoConfigValue(HipoConfigEnum.SPU_REWARD_PERIOD.getConfig());

        Sku sku = skuMapper.findTopOneBySpuId(spu.getId());

        Identity identity = identityMapper.findOneByUserId(user.getId());

        rewardQueueMapper.insert(RewardQueue.builder()
                .userId(user.getId())
                .level(identity == null ? 0 : identity.getLevel())
                .queueStatus(ToggleEnum.OFF.getStatus())
                .rewardStatus(ToggleEnum.OFF.getStatus())
                .createdAt(new Date())
                .updateAt(new Date())
                .orderSkuId(null)
                .spuId(spu.getId())
                .skuId(sku.getId())
                .amount(amount)
                .type(RewardQueueTypeEnum.SPU.getType())
                .rewardType(RewardTypeEnum.SPU.getType())
                .build());

        // 更新排单计数
        BonusCount bonusCount = bonusCountMapper.findOneBySpuId(spu.getId());
        if (bonusCount == null) {
            // 创建排单计数
            bonusCountMapper.insert(BonusCount.builder()
                    .count(0L)
                    .remark(spu.getName())
                    .spuId(spu.getId())
                    .rewardType(RewardTypeEnum.SPU.getType())
                    .build());
        } else {
            bonusCount.setCount(bonusCount.getCount() + 1L);
            if (bonusCount.getCount() >= Long.valueOf(period)) {
                bonusCount.setCount(0L);
                // 发放排单补贴
                RewardQueue rewardQueue = rewardQueueMapper.findOneBySpuIdAndQueueStatusOrderByCreatedAt(spu.getId(), ToggleEnum.OFF.getStatus());
                if (rewardQueue != null) {
                    rewardQueue.setQueueStatus(ToggleEnum.ON.getStatus());
                    rewardQueue.setRewardStatus(ToggleEnum.ON.getStatus());
                    rewardQueue.setUpdateAt(new Date());
                    rewardQueueMapper.updateByPrimaryKeySelective(rewardQueue);
                    UserCommission userCommission = build(rewardQueue.getUserId(), HIPO_USER_ID, rewardQueue.getAmount(), UserCommissionTypeEnum.REWARD_QUEUE_COMMISSION, calendar, rewardQueue.getAmount(), identity == null ? -1 : identity.getType());
                    userCommissionMapper.insert(userCommission);
                }
            }
            bonusCountMapper.updateByPrimaryKeySelective(bonusCount);
        }
    }

    @Override
    public void createRewardQueue(OrderSkuVO orderSkuVO, Spu spu) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 1);
        String period = daoService.getHipoConfigValue(HipoConfigEnum.SPU_REWARD_PERIOD.getConfig());

        Identity identity = identityMapper.findOneByUserId(orderSkuVO.getUserId());

        for (int i = 0; i < orderSkuVO.getCount(); i++) {
            RewardQueue insertRewardQueue = RewardQueue.builder()
                    .userId(orderSkuVO.getUserId())
                    .level(identity == null ? 0 : identity.getLevel())
                    .queueStatus(ToggleEnum.OFF.getStatus())
                    .rewardStatus(ToggleEnum.OFF.getStatus())
                    .createdAt(new Date())
                    .updateAt(new Date())
                    .orderSkuId(orderSkuVO.getId())
                    .spuId(orderSkuVO.getSpuId())
                    .skuId(orderSkuVO.getSkuId())
                    .amount(orderSkuVO.getPrice()) // 免单奖励放大1.2倍
                    .type(RewardQueueTypeEnum.SPU.getType())
                    .rewardType(RewardTypeEnum.SPU.getType())
                    .build();
            rewardQueueMapper.insert(insertRewardQueue);

            // 在这里创建定时任务 1年如果没有免单成功，平台奖励对应的1：1嗨币
            quartzService.createRewardQueueExchangeJob(insertRewardQueue);

            // 更新排单计数
            BonusCount bonusCount = bonusCountMapper.findOneBySpuId(orderSkuVO.getSpuId());
            if (bonusCount == null) {
                // 创建排单计数
                bonusCountMapper.insert(BonusCount.builder()
                        .count(0L)
                        .remark(spu.getName())
                        .spuId(spu.getId())
                        .rewardType(RewardTypeEnum.SPU.getType())
                        .build());
            } else {
                bonusCount.setCount(bonusCount.getCount() + 1L);
                if (bonusCount.getCount() >= Long.valueOf(period)) {
                    bonusCount.setCount(0L);
                    // 发放排单补贴
                    RewardQueue rewardQueue = rewardQueueMapper.findOneBySpuIdAndQueueStatusOrderByCreatedAt(spu.getId(), ToggleEnum.OFF.getStatus());
                    if (rewardQueue != null) {
                        rewardQueue.setQueueStatus(ToggleEnum.ON.getStatus());
                        rewardQueue.setRewardStatus(ToggleEnum.ON.getStatus());
                        rewardQueue.setUpdateAt(new Date());
                        rewardQueueMapper.updateByPrimaryKeySelective(rewardQueue);
                        UserCommission userCommission = buildRewardQueueIssued(rewardQueue.getUserId(),
                                HIPO_USER_ID, rewardQueue.getAmount(),
                                UserCommissionTypeEnum.REWARD_QUEUE_COMMISSION,
                                rewardQueue.getAmount(),
                                identity == null ? -1 : identity.getType(),
                                rewardQueue.getOrderSkuId(), "",
                                rewardQueue.getSpuId());
                        userCommissionMapper.insert(userCommission);
                    }

                }
                bonusCountMapper.updateByPrimaryKeySelective(bonusCount);

            }
        }
    }


    @Override
    public List<UserCommission> prepareCourierCommission(Long ordersId, List<OrderSkuVO> orderSkuVOList, Map<Long, Spu> spuMap) {
        List<UserCommission> userCommissionList = new ArrayList<>();
        List<AgentCommission> agentCommissionList = new ArrayList<>();

        OrderAddress orderAddress = orderAddressMapper.findOneByOrderId(ordersId);

        if (orderAddress == null) {
            return userCommissionList;
        }

        // 获取区域中心代理
        UserAgentLevel userAgentLevel = userAgentLevelMapper.findOneByLocationIdAndExpireTime(orderAddress.getArea(), new Date());


        // 获取区域中心代理
        UserAgentLevel cityUserAgentLevel = userAgentLevelMapper.findOneByLocationIdAndExpireTime(orderAddress.getCity(), new Date());
        if (userAgentLevel == null && cityUserAgentLevel == null) {
            return userCommissionList;
        }

        // 设置冻结时间
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 7);

        Map<String, String> config = daoService.getHipoConfigMap();

        orderSkuVOList.stream().forEach(orderSkuVO -> {
            // 秒杀商品，则跳过
            if ((SpuTypeEnum.NORMAL.getType().equals(spuMap.get(orderSkuVO.getSpuId()).getType())
                    || SpuTypeEnum.ORDINARY.getType().equals(spuMap.get(orderSkuVO.getSpuId()).getType())
                    || SpuTypeEnum.COMMISSION.getType().equals(spuMap.get(orderSkuVO.getSpuId()).getType())) &&
                    !ActivityEnum.FLASH_SALE.getActivity().equals(orderSkuVO.getActivityType())
            ) {

                BigDecimal income = orderSkuVO.getPayAmount()
                        .multiply(new BigDecimal(config.get(HipoConfigEnum.AREA_RATE.getConfig())))
                        .setScale(2, BigDecimal.ROUND_HALF_DOWN);

                BigDecimal cityIncome = orderSkuVO.getPayAmount()
                        .multiply(new BigDecimal(config.get(HipoConfigEnum.CITY_RATE.getConfig())))
                        .setScale(2, BigDecimal.ROUND_HALF_DOWN);

                // 不足1分钱，按1分钱发放
                if (income.compareTo(new BigDecimal(0.01)) < 0) {
                    income = new BigDecimal(0.01);
                }

                // 不足1分钱，按1分钱发放
                if (cityIncome.compareTo(new BigDecimal(0.01)) < 0) {
                    cityIncome = new BigDecimal(0.01);
                }


                if (userAgentLevel != null) {
                    // 寻找这个区域中心的直推上级，发10元1笔
                    Identity identity = getSuperiorIdentity(userAgentLevel.getUserId());
                    if (identity != null && identity.getMemberState().equals(MemberStateEnum.SUPER.getType())) {
                        userCommissionList.add(
                                UserCommission.builder()
                                        .superiorId(identity.getUserId())
                                        .subordinateId(userAgentLevel.getUserId())
                                        .orderSkuId(orderSkuVO.getId())
                                        .commission(BigDecimal.TEN.multiply(BigDecimal.valueOf(orderSkuVO.getCount())))
                                        .type(UserCommissionTypeEnum.AREA_DIVIDENDS.getType())
                                        .freezeTime(calendar.getTime())
                                        .status(UserCommissionStatusEnum.FREEZE.getStatus())
                                        .relateId(orderSkuVO.getSpuId())
                                        .remark(orderSkuVO.getProductName())
                                        .createdAt(new Date())
                                        .updatedAt(new Date())
                                        .amount(orderSkuVO.getPayAmount())
                                        .identityType((byte) -1)
                                        .businessType(UserCommissionBusinessTypeEnum.USER.getType())
                                        .build());
                    }
                    addAgentCommission(userCommissionList, agentCommissionList, userAgentLevel, orderSkuVO, orderAddress, UserCommissionTypeEnum.AREA_DIVIDENDS.getType(), calendar, income, UserAgentLevelEnum.AREA.getType());
                }

                if (cityUserAgentLevel != null) {
                    addAgentCommission(userCommissionList, agentCommissionList, cityUserAgentLevel, orderSkuVO, orderAddress, UserCommissionTypeEnum.CITY_DIVIDENDS.getType(), calendar, cityIncome, UserAgentLevelEnum.CITY.getType());
                    if (userAgentLevel == null) {
                        // 寻找这个区域中心的直推上级，发10元1笔
                        Identity identity = getSuperiorIdentity(cityUserAgentLevel.getUserId());
                        if (identity != null && identity.getMemberState().equals(MemberStateEnum.SUPER.getType())) {
                            userCommissionList.add(
                                    UserCommission.builder()
                                            .superiorId(identity.getUserId())
                                            .subordinateId(cityUserAgentLevel.getUserId())
                                            .orderSkuId(orderSkuVO.getId())
                                            .commission(BigDecimal.TEN.multiply(BigDecimal.valueOf(orderSkuVO.getCount())))
                                            .type(UserCommissionTypeEnum.CITY_DIVIDENDS.getType())
                                            .freezeTime(calendar.getTime())
                                            .status(UserCommissionStatusEnum.FREEZE.getStatus())
                                            .relateId(orderSkuVO.getSpuId())
                                            .remark(orderSkuVO.getProductName())
                                            .createdAt(new Date())
                                            .updatedAt(new Date())
                                            .amount(orderSkuVO.getPayAmount())
                                            .identityType((byte) -1)
                                            .businessType(UserCommissionBusinessTypeEnum.USER.getType())
                                            .build());
                        }

                        addAgentCommission(userCommissionList, agentCommissionList, cityUserAgentLevel, orderSkuVO, orderAddress, UserCommissionTypeEnum.AREA_DIVIDENDS.getType(), calendar, income, UserAgentLevelEnum.AREA.getType());
                    }
                }
            }
        });

        if (!agentCommissionList.isEmpty()) {
            agentCommissionMapper.batchInsert(agentCommissionList);
        }

        return userCommissionList;
    }

    //区域代理冻结佣金记录和区域代理收入记录
    private void addAgentCommission(List<UserCommission> userCommissionList, List<AgentCommission> agentCommissionList, UserAgentLevel userAgentLevel, OrderSkuVO orderSkuVO, OrderAddress orderAddress, Byte userCommissionType, Calendar calendar, BigDecimal income, Byte agentCommissionType) {
        userCommissionList.add(
                UserCommission.builder()
                        .superiorId(userAgentLevel.getUserId())
                        .subordinateId(orderAddress.getUserId())
                        .orderSkuId(orderSkuVO.getId())
                        .commission(income)
                        .type(userCommissionType)
                        .freezeTime(calendar.getTime())
                        .status(UserCommissionStatusEnum.FREEZE.getStatus())
                        .relateId(orderSkuVO.getSpuId())
                        .remark(orderSkuVO.getProductName())
                        .createdAt(new Date())
                        .updatedAt(new Date())
                        .amount(orderSkuVO.getPayAmount())
                        .identityType((byte) -1)
                        .businessType(UserCommissionBusinessTypeEnum.USER.getType())
                        .build());

        agentCommissionList.add(
                AgentCommission.builder()
                        .orderId(orderSkuVO.getOrderId())
                        .orderSkuId(orderSkuVO.getId())
                        .userId(orderSkuVO.getUserId())
                        .agentUserId(userAgentLevel.getUserId())
                        .type(agentCommissionType)
                        .province(orderAddress.getProvince())
                        .city(orderAddress.getCity())
                        .area(orderAddress.getArea())
                        .mergerName(orderAddress.getMergerName())
                        .count(orderSkuVO.getCount())
                        .commission(income)
                        .createdAt(new Date())
                        .updatedAt(new Date())
                        .commissionType(AgentCommissionTypeEnum.BONUS.getType())
                        .amount(orderSkuVO.getPayAmount())
                        .build());
    }


    /**
     * 获取此人绑定的上级的身份实体
     *
     * @param subordinateId
     * @return
     */
    public Identity getSuperiorIdentity(Long subordinateId) {
        UserRelationship userRelationship = userRelationshipMapper.findOneBySubordinateId(subordinateId);
        if (userRelationship != null) {
            return identityMapper.findOneByUserId(userRelationship.getSuperiorId());
        }
        return null;
    }

    /**
     * 获取指定用户的上级会员
     *
     * @param subordinateId
     * @return
     */
    public Long getSuperiorMember(Long subordinateId) {
        Map<Long, Boolean> map = new HashMap<>();
        Long sub = subordinateId;
        Long superiorId = null;
        do {
            // 如果已经存在，说明进入循环了
            if (!map.containsKey(sub)) {
                map.put(sub, true);
                UserRelationship userRelationship = userRelationshipMapper.findOneBySubordinateId(sub);
                if (userRelationship != null) {
                    Identity superIdentity = identityMapper.findOneByUserId(userRelationship.getSuperiorId());
                    if (superIdentity != null && superIdentity.getMemberLevel() >= UserLevelEnum.MEMBER_L1.getLevel() && MemberStateEnum.SUPER.getType().equals(superIdentity.getMemberState())) {
                        superiorId = superIdentity.getUserId();
                    } else {
                        sub = userRelationship.getSuperiorId();
                    }
                } else {
                    superiorId = HIPO_USER_ID;
                }
            } else {
                superiorId = HIPO_USER_ID;
            }
        } while (superiorId == null);
        return superiorId;
    }

    /**
     * 获取指定用户的上级合伙人
     *
     * @param subordinateId
     * @return
     */
    public Long getSuperiorPartner(Long subordinateId) {
        Map<Long, Boolean> map = new HashMap<>();
        Long sub = subordinateId;
        Long superiorId = null;
        do {
            // 如果已经存在，说明进入循环了
            if (!map.containsKey(sub)) {
                map.put(sub, true);
                UserRelationship userRelationship = userRelationshipMapper.findOneBySubordinateId(sub);
                if (userRelationship != null) {
                    Identity superIdentity = identityMapper.findOneByUserId(userRelationship.getSuperiorId());
                    if (superIdentity != null && superIdentity.getPartnerLevel() >= UserLevelEnum.PARTNER_L1.getLevel()) {
                        superiorId = superIdentity.getUserId();
                    } else {
                        sub = userRelationship.getSuperiorId();
                    }
                } else {
                    superiorId = HIPO_USER_ID;
                }
            } else {
                superiorId = HIPO_USER_ID;
            }
        } while (superiorId == null);
        return superiorId;
    }

    /**
     * 获取指定用户的上级运营中心
     *
     * @param subordinateId
     * @return
     */
    @Override
    public Long getSuperiorShareholder(Long subordinateId) {
        Map<Long, Boolean> map = new HashMap<>();
        Long sub = subordinateId;
        Long superiorId = null;
        do {
            // 如果已经存在，说明进入循环了
            if (!map.containsKey(sub)) {
                map.put(sub, true);
                UserRelationship userRelationship = userRelationshipMapper.findOneBySubordinateId(sub);
                if (userRelationship != null) {
                    Identity superIdentity = identityMapper.findOneByUserId(userRelationship.getSuperiorId());
                    if (superIdentity != null && superIdentity.getShareholderLevel() >= UserLevelEnum.SHAREHOLDER_L1.getLevel()) {
                        superiorId = superIdentity.getUserId();
                    } else {
                        sub = userRelationship.getSuperiorId();
                    }
                } else {
                    superiorId = HIPO_USER_ID;
                }
            } else {
                superiorId = HIPO_USER_ID;
            }
        } while (superiorId == null);
        return superiorId;
    }

    /**
     * 获取指定用户的上级合伙人或运营中心
     *
     * @param subordinateId
     * @return
     */
    public Map<Integer, Long> getSuperiorPartnerOrShareholder(Long subordinateId) {
        Map<Integer, Long> superiorMap = new HashMap<>();

        Identity identity = identityMapper.findOneByUserId(subordinateId);

        if (identity != null) {
            if (identity.getLevel() >= UserLevelEnum.SHAREHOLDER_L1.getLevel()) {
                superiorMap.put(UserLevelEnum.SHAREHOLDER_L1.getLevel(), identity.getUserId());
                return superiorMap;
            } else if (identity.getLevel() >= UserLevelEnum.PARTNER_L1.getLevel()) {
                superiorMap.put(UserLevelEnum.PARTNER_L1.getLevel(), identity.getUserId());
            }
        }

        Map<Long, Boolean> map = new HashMap<>();
        Long sub = subordinateId;
        boolean keepRun = true;
        do {
            // 如果已经存在，说明进入循环了
            if (!map.containsKey(sub)) {
                map.put(sub, true);
                UserRelationship userRelationship = userRelationshipMapper.findOneBySubordinateId(sub);
                if (userRelationship != null) {
                    Identity superIdentity = identityMapper.findOneByUserId(userRelationship.getSuperiorId());
                    if (superIdentity != null && superIdentity.getLevel() >= UserLevelEnum.PARTNER_L1.getLevel()) {
                        if (superIdentity.getLevel() >= UserLevelEnum.SHAREHOLDER_L1.getLevel()) {
                            // 如果遇到运营中心，说明已经到头。
                            superiorMap.put(UserLevelEnum.SHAREHOLDER_L1.getLevel(), superIdentity.getUserId());
                            keepRun = false;
                        } else {

                            if (!superiorMap.containsKey(UserLevelEnum.PARTNER_L1.getLevel())) {
                                // 如果当前还没有人为一级合伙人，则设置为一级合伙人
                                superiorMap.put(UserLevelEnum.PARTNER_L1.getLevel(), superIdentity.getUserId());
                            } else {
                                // 如果当前还没有二级合伙人（仅仅只是利用一下这L2这个数字，并不是表示他是L2）
                                if (!superiorMap.containsKey(UserLevelEnum.PARTNER_L2.getLevel())) {
                                    superiorMap.put(UserLevelEnum.PARTNER_L2.getLevel(), superIdentity.getUserId());
                                }
                            }
                        }
                    }
                    sub = userRelationship.getSuperiorId();
                } else {
                    keepRun = false;
                }
            } else {
                keepRun = false;
            }
        } while (keepRun);

        return superiorMap;
    }


    /**
     * 获取指定用户的上级合伙人L2及以上，包括自己
     *
     * @param subordinateId
     * @return
     */
    public Map<Integer, Long> getSuperiorMap(Long subordinateId) {
        Map<Integer, Long> superiorMap = new HashMap<>();

        Identity identity = identityMapper.findOneByUserId(subordinateId);

        if (UserLevelEnum.PARTNER_L4.getLevel().equals(identity.getPartnerLevel())) {
            superiorMap.put(UserLevelEnum.PARTNER_L4.getLevel(), identity.getUserId());
            return superiorMap;
        }

        if (UserLevelEnum.PARTNER_L3.getLevel().equals(identity.getPartnerLevel())) {
            superiorMap.put(UserLevelEnum.PARTNER_L3.getLevel(), identity.getUserId());
        }

        if (UserLevelEnum.PARTNER_L2.getLevel().equals(identity.getPartnerLevel())) {
            superiorMap.put(UserLevelEnum.PARTNER_L2.getLevel(), identity.getUserId());
        }

        Map<Long, Boolean> map = new HashMap<>();
        Long sub = subordinateId;
        boolean keepRun = true;
        do {
            // 如果已经存在，说明进入循环了
            if (!map.containsKey(sub)) {
                map.put(sub, true);
                UserRelationship userRelationship = userRelationshipMapper.findOneBySubordinateId(sub);
                if (userRelationship != null) {
                    Identity superIdentity = identityMapper.findOneByUserId(userRelationship.getSuperiorId());
                    if (superIdentity != null && superIdentity.getPartnerLevel() > UserLevelEnum.PARTNER_L1.getLevel()) {
                        // 不能有其他人，才能登记L2
                        if (UserLevelEnum.PARTNER_L2.getLevel().equals(superIdentity.getPartnerLevel()) && superiorMap.isEmpty()) {
                            superiorMap.put(UserLevelEnum.PARTNER_L2.getLevel(), superIdentity.getUserId());
                        }
                        // 不能有其他人L3,L4，才能登记L3
                        if (UserLevelEnum.PARTNER_L3.getLevel().equals(superIdentity.getPartnerLevel()) && !superiorMap.containsKey(UserLevelEnum.PARTNER_L3.getLevel())) {
                            superiorMap.put(UserLevelEnum.PARTNER_L3.getLevel(), superIdentity.getUserId());
                        }
                        if (UserLevelEnum.PARTNER_L4.getLevel().equals(superIdentity.getPartnerLevel())) {
                            superiorMap.put(UserLevelEnum.PARTNER_L4.getLevel(), superIdentity.getUserId());
                            keepRun = false;
                        }
                    }
                    sub = userRelationship.getSuperiorId();
                } else {
                    keepRun = false;
                }
            } else {
                keepRun = false;
            }
        } while (keepRun);
        return superiorMap;
    }

    void updateMemberLevel(Long userId, Long count) {
        Identity supIdentity = null;
        Identity identity = identityMapper.findOneByUserId(userId);
        if (identity.getMemberLevel() >= UserLevelEnum.MEMBER_L1.getLevel()) {
            supIdentity = identity;
        } else {
            Long superiorId = getSuperiorMember(userId);
            if (HIPO_USER_ID != superiorId) {
                supIdentity = identityMapper.findOneByUserId(superiorId);
            }
        }

        if (supIdentity != null) {
            // 增加进货套数，并升级
            supIdentity.setSellCount(supIdentity.getSellCount() + count);

            if (supIdentity.getSellCount() >= 200L) {
                supIdentity.setMemberLevel(UserLevelEnum.MEMBER_L3.getLevel());
                if (supIdentity.getLevel() < UserLevelEnum.MEMBER_L3.getLevel()) {
                    supIdentity.setLevel(UserLevelEnum.MEMBER_L3.getLevel());
                }
            } else if (supIdentity.getSellCount() >= 50L) {
                supIdentity.setMemberLevel(UserLevelEnum.MEMBER_L2.getLevel());
                if (supIdentity.getLevel() < UserLevelEnum.MEMBER_L2.getLevel()) {
                    supIdentity.setLevel(UserLevelEnum.MEMBER_L2.getLevel());
                }
            }

            identityMapper.updateByPrimaryKeySelective(supIdentity);

            Long superiorMember = getSuperiorMember(supIdentity.getUserId());
            if (HIPO_USER_ID != superiorMember) {
                updateMemberLevel(superiorMember, count);
            }
        }
    }

    void updatePartnerLevel(Long userId, Long count) {
        Identity supIdentity = null;
        Identity identity = identityMapper.findOneByUserId(userId);
        if (identity.getPartnerLevel() >= UserLevelEnum.PARTNER_L1.getLevel()) {
            supIdentity = identity;
        } else {
            Long superiorId = getSuperiorPartner(userId);
            if (HIPO_USER_ID != superiorId) {
                supIdentity = identityMapper.findOneByUserId(superiorId);
            }
        }

        if (supIdentity != null) {
            // 增加进货套数，并升级
            supIdentity.setSellCount(supIdentity.getSellCount() + count);

            if (supIdentity.getSellCount() >= 3000L) {
                supIdentity.setPartnerLevel(UserLevelEnum.PARTNER_L4.getLevel());
                if (supIdentity.getLevel() < UserLevelEnum.PARTNER_L4.getLevel()) {
                    supIdentity.setLevel(UserLevelEnum.PARTNER_L4.getLevel());
                }
            } else if (supIdentity.getSellCount() >= 1000L) {
                supIdentity.setPartnerLevel(UserLevelEnum.PARTNER_L3.getLevel());
                if (supIdentity.getLevel() < UserLevelEnum.PARTNER_L3.getLevel()) {
                    supIdentity.setLevel(UserLevelEnum.PARTNER_L3.getLevel());
                }
            } else if (supIdentity.getSellCount() >= 100L) {
                supIdentity.setPartnerLevel(UserLevelEnum.PARTNER_L2.getLevel());
                if (supIdentity.getLevel() < UserLevelEnum.PARTNER_L2.getLevel()) {
                    supIdentity.setLevel(UserLevelEnum.PARTNER_L2.getLevel());
                }
            }

            identityMapper.updateByPrimaryKeySelective(supIdentity);
        }
    }

    /**
     * @param source 需要过滤的字符串
     * @return
     */
    public static String subShopOrderPayBodyString(String source) {
        if (source.length() > 20) {
            return source.substring(0, 19);
        }
        return source;
    }


    /**
     * 抢购成功
     *
     * @param orderSku
     */
    public void rushBuySuccess(OrderSku orderSku, Orders orders, Map<String, String> config) {
        // 设置冻结时间
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 7);

        // 发放代理身份
        User user = userMapper.selectByPrimaryKey(orderSku.getUserId());
//        levelService.addOneMember(user, IsBuyerEnum.BUYER.getType(), MemberStateEnum.SUPER.getType());

        // 发放待释放的福利补贴
        // 取消翻倍
        Identity identity = identityMapper.findOneByUserId(user.getId());
        BigDecimal amount = orderSku.getPayAmount();
        BigDecimal point = identity.getWelfare().add(amount);
        identityMapper.updateWelfareAndUpdateAtById(point, new Date(), identity.getId());

        welfareFlowMapper.insert(WelfareFlow.builder()
                .userId(user.getId())
                .amount(amount)
                .tradeType(WelfareFlowTradeTypeEnum.COMMISSION_ORDER.getTradeType())
                .type(WelfareFlowTradeTypeEnum.COMMISSION_ORDER.getType())
                .point(point)
                .createdAt(new Date())
                .build());

        // 订单确认了，可以进行发货了
        Shop shop = shopMapper.selectByPrimaryKey(orders.getShopId());
        if (shop != null && shop.getUserId() != null) {
            smsService.sendShopOrderSms(
                    subShopOrderPayBodyString((user.getNickname().length() > 5 ? user.getNickname().substring(0, 5) : user.getNickname()) + "|" + orderSku.getProductName()),
                    userMapper.selectByPrimaryKey(shop.getUserId()).getUsername()
            );
        }
        if (orders.getTotalPayAmount().compareTo(BigDecimal.ZERO) > 0) {
            // 每个订单里最多只能有1个商品

            // 立即发放商品销售收入给商户
            Tenant tenant = tenantMapper.selectByPrimaryKey(shop.getId());
            tenantFlowMapper.insert(TenantFlow.builder()
                    .amount(orders.getTotalTenantAmount())
                    .tradeType(TenantTradeTypeEnum.PRODUCT.getTradeType())
                    .type(TenantTradeTypeEnum.PRODUCT.getType())
                    .point(tenant.getPoint().add(orders.getTotalTenantAmount()))
                    .relateId(orders.getId())
                    .remark(orderSku.getProductName())
                    .createdAt(new Date())
                    .tenantId(tenant.getId())
                    .build());
            tenantMapper.updatePointById(tenant.getPoint().add(orders.getTotalTenantAmount()), tenant.getId());
            financeService.createFreezeAmount(orders, orders.getTotalTenantAmount(), FreezeTypeEnum.ORDERS.getType());
        }

        // 上级代理得15%的直推佣金
        Identity superiorIdentity = getSuperiorIdentity(user.getId());
        if (superiorIdentity != null && MemberStateEnum.SUPER.getType().equals(superiorIdentity.getMemberState())) {

            // 优先加速释放福利补贴
            if (superiorIdentity.getWelfare().compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal rate = new BigDecimal(config.get(HipoConfigEnum.DIRECT_RECOMMEND_COMMISSION_RATE.getConfig()));
                BigDecimal commission = orderSku.getPayAmount().multiply(rate).setScale(2, BigDecimal.ROUND_HALF_UP);

                BigDecimal releaseWelfare = commission;
                if (superiorIdentity.getWelfare().compareTo(commission) < 0) {
                    // 不足够释放，则释放剩余的部分
                    releaseWelfare = superiorIdentity.getWelfare();
                }

                BigDecimal releasePoint = superiorIdentity.getWelfare().subtract(releaseWelfare);
                identityMapper.updateWelfareAndUpdateAtById(releasePoint, new Date(), superiorIdentity.getId());

                welfareFlowMapper.insert(WelfareFlow.builder()
                        .userId(superiorIdentity.getUserId())
                        .amount(releaseWelfare)
                        .tradeType(WelfareFlowTradeTypeEnum.DIRECT_RECOMMEND_COMMISSION.getTradeType())
                        .type(WelfareFlowTradeTypeEnum.DIRECT_RECOMMEND_COMMISSION.getType())
                        .point(releasePoint)
                        .createdAt(new Date())
                        .build());

                // 如果上级没有合伙人身份，则只能获得待释放福利补贴内的直推佣金
                if (superiorIdentity.getPartnerLevel() < UserLevelEnum.PARTNER_L1.getLevel()) {
                    UserCommission userCommission = build(superiorIdentity.getUserId(), orderSku.getUserId(), releaseWelfare, UserCommissionTypeEnum.DIRECT_RECOMMEND_COMMISSION, calendar, orderSku.getPayAmount(), IdentityTypeEnum.MEMBER.getType(), orderSku.getId(), orderSku.getProductName(), IdentityTypeEnum.MEMBER.getType());
                    userCommissionMapper.insert(userCommission);
                    // 发放佣金
                    issueUserCommission(userCommission);
                }
            }
        }

        if (superiorIdentity != null
                && superiorIdentity.getPartnerLevel() >= UserLevelEnum.PARTNER_L1.getLevel()
                && superiorIdentity.getPartnerExpireTime() != null
                && superiorIdentity.getPartnerExpireTime().after(new Date())) {
            //获得抢购免单成功业绩5%收入
            BigDecimal storeCommission = orderSku.getPayAmount().multiply(new BigDecimal(config.get(HipoConfigEnum.RUSH_SUCCESS_COMMISSION_RATE.getConfig()))).setScale(2, BigDecimal.ROUND_HALF_UP);
            UserCommission storeUserCommission = build(superiorIdentity.getUserId(), orderSku.getUserId(), storeCommission, UserCommissionTypeEnum.RUSH_SUCCESS_COMMISSION, calendar, orderSku.getPayAmount(), IdentityTypeEnum.PARTNER.getType(), orderSku.getId(), orderSku.getProductName(), IdentityTypeEnum.PARTNER.getType());
            userCommissionMapper.insert(storeUserCommission);
            issueUserCommission(storeUserCommission);
        }

        createPartnerPerformance(orderSku, superiorIdentity);

        List<OrderSkuVO> orderSkuVOList = new ArrayList<>();
        OrderSkuVO orderSkuVO = new OrderSkuVO();
        BeanUtils.copyProperties(orderSku, orderSkuVO);
        orderSkuVOList.add(orderSkuVO);
        prepareFinalCommission(orderSkuVOList, config);
    }

    /**
     * 抢购失败
     *
     * @param rushBuyList
     */
    public void rushBuyFail(List<OrderSku> rushBuyList) {
        // 设置冻结时间
        Calendar calendar = Calendar.getInstance();

        rushBuyList.stream().forEach(item -> {

            List<UserCommission> commissions = new ArrayList<>();

            // 1、得5%的广告补贴
            BigDecimal commission = item.getPayAmount().multiply(BigDecimal.valueOf(0.05)).setScale(2, BigDecimal.ROUND_HALF_UP);
            commissions.add(build(item.getUserId(), HIPO_USER_ID, commission, UserCommissionTypeEnum.MEMBER_BONUS, calendar, item.getPayAmount(), IdentityTypeEnum.MEMBER.getType(), item.getId(), item.getProductName(), IdentityTypeEnum.MEMBER.getType()));

            // 2、上级得5%的爱心奖（所有上级（包括普通用户和代理））
            Identity superiorIdentity = getSuperiorIdentity(item.getUserId());
            if (superiorIdentity != null) {
                BigDecimal love = item.getPayAmount().multiply(BigDecimal.valueOf(0.05)).setScale(2, BigDecimal.ROUND_HALF_UP);
                commissions.add(build(superiorIdentity.getUserId(), item.getUserId(), love, UserCommissionTypeEnum.LOVE_COMMISSION, calendar, item.getPayAmount(), IdentityTypeEnum.MEMBER.getType(), item.getId(), item.getProductName(), IdentityTypeEnum.MEMBER.getType()));
            }

            // 直接先发放佣金，避免因为退款导致佣金收回！
            if (!CollectionUtils.isEmpty(commissions)) {
                userCommissionMapper.batchInsert(commissions);
                commissions.stream().forEach(each -> {
                    // 发放佣金
                    issueUserCommission(each);
                });
            }

            // 3、关闭订单
            commonOrderService.closeOrder(ordersMapper.selectByPrimaryKey(item.getOrderId()));
        });
    }


    /**
     * @param orderSkuVOList
     */
    @Override
    public void prepareHipoCommission(List<OrderSkuVO> orderSkuVOList) {
        Orders orders = ordersMapper.selectByPrimaryKey(orderSkuVOList.get(0).getOrderId());
        Map<String, String> config = daoService.getHipoConfigMap();

        // 先判断是否是抢购，
        if (OrderKindEnum.COMMISSION.getKind().equals(orderSkuVOList.get(0).getOrderKind()) && RushTypeEnum.RUSH.getType().equals(orderSkuVOList.get(0).getRushType())) {
            // 判断当前的spuId是否已经达到5人抢购中
            List<OrderSku> rushBuyList = orderSkuMapper.findFiveRushBuy(orderSkuVOList.get(0).getSpuId(), OrderKindEnum.COMMISSION.getKind(), RushBuyStatusEnum.PENDING.getStatus());
            if (rushBuyList.size() >= 5) {
                // 开抢，先随机获得中奖人
                Random r = new Random();
                int a = r.nextInt(5);

                String rushBuyNo = Long.toString(uidGenerator.getUID());

                // 先立即变更订单状态，以免并发时，被其他sql同时获取了
                OrderSku orderSku = rushBuyList.remove(a);
                orderSkuMapper.updateRushBuyStatusAndRushBuyNoById(RushBuyStatusEnum.SUCCESS.getStatus(), rushBuyNo, orderSku.getId());
                ordersMapper.updateRushBuyStatusById(RushBuyStatusEnum.SUCCESS.getStatus(), orderSku.getOrderId());

                int b = r.nextInt(4);
                OrderSku orderSku2 = rushBuyList.remove(b);
                orderSkuMapper.updateRushBuyStatusAndRushBuyNoById(RushBuyStatusEnum.SUCCESS.getStatus(), rushBuyNo, orderSku2.getId());
                ordersMapper.updateRushBuyStatusById(RushBuyStatusEnum.SUCCESS.getStatus(), orderSku2.getOrderId());

                orderSkuMapper.updateRushBuyStatusAndRushBuyNoByIdIn(RushBuyStatusEnum.FAIL.getStatus(), rushBuyNo, rushBuyList.stream().map(OrderSku::getId).collect(Collectors.toList()));
                ordersMapper.updateRushBuyStatusByIdIn(RushBuyStatusEnum.FAIL.getStatus(), rushBuyList.stream().map(OrderSku::getOrderId).collect(Collectors.toList()));

                rushBuySuccess(orderSku, orders, config);
                rushBuySuccess(orderSku2, orders, config);
                rushBuyFail(rushBuyList);
            }
        } else {
            prepareFinalCommission(orderSkuVOList, config);
        }
    }

    public void prepareFinalCommission(List<OrderSkuVO> orderSkuVOList, Map<String, String> config) {
        List<UserCommission> commissions = new ArrayList<>();
        User user = userMapper.selectByPrimaryKey(orderSkuVOList.get(0).getUserId());

        String memberSpu = config.get(HipoConfigEnum.MEMBER_SPU.getConfig());
        String partnerSpu = config.get(HipoConfigEnum.PARTNER_SPU.getConfig());
        String shareholderSpu = config.get(HipoConfigEnum.SHAREHOLDER_SPU.getConfig());
        Boolean useCommissionCount = false;
        // 设置冻结时间
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 7);

        Map<Long, Spu> spuMap = daoService.getSpuMap(orderSkuVOList.stream().map(OrderSku::getSpuId).collect(Collectors.toList()));
        Map<Long, Sku> skuMap = daoService.getSkuMap(orderSkuVOList.stream().map(OrderSku::getSkuId).collect(Collectors.toList()));

        //在此得到当前订单使用的优惠券
        OrderDiscount orderDiscount = orderDiscountMapper.findOneByOrderIdAndType(orderSkuVOList.get(0).getOrderId(), PromotionEnum.COUPON.getPromotion());

        for (OrderSkuVO item : orderSkuVOList) {
            //if 存在优惠券 在这里计算得到真实的支付金额（payAmount 通用券则按比例扣减，指定券则全额扣减），直接setPayAmount
            if (orderDiscount != null) {
                Coupon coupon = couponMapper.selectByPrimaryKey(orderDiscount.getRelateId());
                BigDecimal eachCouponAmount = BigDecimal.ZERO;
                if (OrderDiscountLevelEnum.ORDER_LEVEL.getType().equals(orderDiscount.getLevel())) {
                    //订单级优惠券
                    BigDecimal totalPayAmount = orderSkuVOList.stream().map(ordersku -> ordersku.getPayAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
                    //orderSku分摊优惠券金额
                    eachCouponAmount = item.getPayAmount().divide(totalPayAmount, 2, BigDecimal.ROUND_HALF_DOWN).multiply(coupon.getDiscountAmount()).setScale(2, BigDecimal.ROUND_HALF_DOWN);
                } else if (OrderDiscountLevelEnum.SPU_LEVEL.getType().equals(orderDiscount.getLevel())) {
                    //商品级优惠券
                    if (item.getSpuId().equals(coupon.getSpuId())) {
                        eachCouponAmount = coupon.getDiscountAmount();
                    }
                }
                item.setPayAmount(item.getPayAmount().subtract(eachCouponAmount));
            }


            // 秒杀商品，则跳过
            if (ActivityEnum.FLASH_SALE.getActivity().equals(item.getActivityType())) {
                //会员购买了秒杀商品 给小店1%的嗨币
                Identity currentIdentity = identityMapper.findOneByUserId(user.getId());
                if (currentIdentity != null
                        && IdentityTypeEnum.MEMBER.getType().equals(currentIdentity.getType())
                        && MemberStateEnum.SUPER.getType().equals(currentIdentity.getMemberState())
                        && currentIdentity.getMemberExpireTime() != null
                        && currentIdentity.getMemberExpireTime().after(new Date())) {
                    Identity superiorIdentity = getSuperiorIdentity(item.getUserId());
                    if (superiorIdentity != null
                            && IdentityTypeEnum.PARTNER.getType().equals(superiorIdentity.getType())
                            && superiorIdentity.getPartnerExpireTime() != null
                            && superiorIdentity.getPartnerExpireTime().after(new Date())) {
                        BigDecimal addCardPoint = item.getPayAmount().multiply(new BigDecimal(config.get(HipoConfigEnum.PARTNER_MEMBER_FLASH_SALE_RATE.getConfig())));
                        User superiorUser = userMapper.selectByPrimaryKey(superiorIdentity.getUserId());
                        BigDecimal cardPoint = superiorUser.getCardPoint().add(addCardPoint);
                        userMapper.updateCardPointById(cardPoint, superiorUser.getId());
                        cardFlowMapper.insert(CardFlow.builder()
                                .userId(superiorUser.getId())
                                .amount(addCardPoint)
                                .tradeType(CardTradeTypeEnum.PARTNER_MEMBER_FLASH_SALE_REWARD.getTradeType())
                                .type(CardTradeTypeEnum.PARTNER_MEMBER_FLASH_SALE_REWARD.getType())
                                .cardPoint(cardPoint)
                                .relateId(item.getId())
                                .remark("小店下会员购买了秒杀商品获得嗨币")
                                .createdAt(new Date())
                                .build());
                    }
                }
                continue;
            }

            Spu spu = spuMap.get(item.getSpuId());
            boolean isMemberSpu = item.getSpuId().equals(Long.valueOf(memberSpu));
            boolean isPartnerSpu = item.getSpuId().equals(Long.valueOf(partnerSpu));
            boolean isOrdinarySpu = SpuTypeEnum.ORDINARY.getType().equals(spu.getType());
            boolean isStoreSpu = SpuTypeEnum.PARTNER.getType().equals(spu.getType());
            boolean isShareholderSpu = item.getSpuId().equals(Long.valueOf(shareholderSpu));

            // 发放会员身份
            if (isMemberSpu) {
                // 如果购买了多个，则重复发放，续期
                // 买1年送1年
                for (int i = 0; i < (item.getCount() * 2); i++) {
                    levelService.addOneMember(user, IsBuyerEnum.BUYER.getType(), MemberStateEnum.SUPER.getType());
                }
            }

            // 发放合伙人身份
            if (isOrdinarySpu && isPartnerSpu) {
                // 如果购买了多个，则重复发放，续期
                for (int i = 0; i < item.getCount(); i++) {
                    levelService.addOnePartner(user, IsBuyerEnum.BUYER.getType());
                }
            }

            // 发放运营中心身份  | 联合创始人身份
            if (isShareholderSpu) {
                levelService.addOneShareholder(user, IsBuyerEnum.BUYER.getType());
                Identity identity = identityMapper.findOneByUserId(user.getId());
                identity.setDirector((byte) 1);
                identityMapper.updateByPrimaryKey(identity);
            }

            // 会员或合伙人直推会员
            if (isMemberSpu) {
                Identity identity = getSuperiorIdentity(item.getUserId());

                //上级为合伙人
                if (identity != null
                        && IdentityTypeEnum.PARTNER.getType().equals(identity.getType())
                        && identity.getPartnerExpireTime() != null
                        && identity.getPartnerExpireTime().after(new Date())) {
                    if (identity.getMemberAccount() > 0) {
                        useCommissionCount = true;
                        commissions.add(build(identity.getUserId(), user.getId(), item.getPrice(), UserCommissionTypeEnum.VIP_CHANCE_COMMISSION, calendar, item.getPayAmount(), IdentityTypeEnum.PARTNER.getType(), item.getId(), item.getProductName(), IdentityTypeEnum.MEMBER.getType()));

                        //会员佣金次数扣减
                        identityMapper.updateMemberAccountAndUpdateAtByUserId(identity.getMemberAccount() - 1, new Date(), identity.getUserId());
                    } else {
                        //上级合伙人直推会员得50%佣金
                        BigDecimal commission = item.getPayAmount().multiply(new BigDecimal(config.get(HipoConfigEnum.PARTNER_COMMISSION_RATE.getConfig()))).setScale(2, BigDecimal.ROUND_HALF_UP);
                        commissions.add(build(identity.getUserId(), user.getId(), commission, UserCommissionTypeEnum.PARTNER_SHARE_COMMISSION, calendar, item.getPayAmount(), IdentityTypeEnum.PARTNER.getType(), item.getId(), item.getProductName(), IdentityTypeEnum.MEMBER.getType()));
                    }

                    //更新会员等级
                    updateMemberLevel(identity.getUserId(), Long.valueOf(item.getCount()));
                }


                //上级为会员
                if (identity != null
                        && IdentityTypeEnum.MEMBER.getType().equals(identity.getType())
                        && MemberStateEnum.SUPER.getType().equals(identity.getMemberState())
                        && identity.getMemberExpireTime() != null
                        && identity.getMemberExpireTime().after(new Date())) {
                    // 上级会员得40%的直推佣金
                    BigDecimal commission = item.getPayAmount().multiply(new BigDecimal(config.get(HipoConfigEnum.MEMBER_COMMISSION_RATE.getConfig()))).setScale(2, BigDecimal.ROUND_HALF_UP);
                    commissions.add(build(identity.getUserId(), user.getId(), commission, UserCommissionTypeEnum.MEMBER_SHARE_COMMISSION, calendar, item.getPayAmount(), IdentityTypeEnum.MEMBER.getType(), item.getId(), item.getProductName(), IdentityTypeEnum.MEMBER.getType()));

                    //上级会员获得嗨币 根据会员等级
                    BigDecimal addCardPoint = item.getPayAmount().multiply(getCardPointRate(identity, config));
                    User superiorUser = userMapper.selectByPrimaryKey(identity.getUserId());
                    BigDecimal cardPoint = superiorUser.getCardPoint().add(addCardPoint);
                    userMapper.updateCardPointById(cardPoint, superiorUser.getId());
                    cardFlowMapper.insert(CardFlow.builder()
                            .userId(superiorUser.getId())
                            .amount(addCardPoint)
                            .tradeType(CardTradeTypeEnum.DIRECT_CARD_POINT_REWARD.getTradeType())
                            .type(CardTradeTypeEnum.DIRECT_CARD_POINT_REWARD.getType())
                            .cardPoint(cardPoint)
                            .relateId(item.getId())
                            .remark("会员直推会员嗨币")
                            .createdAt(new Date())
                            .build());

                    //更新会员等级
                    updateMemberLevel(identity.getUserId(), Long.valueOf(item.getCount()));

                    Identity superiorIdentity = getSuperiorIdentity(identity.getUserId());
                    if (superiorIdentity != null
                            && IdentityTypeEnum.PARTNER.getType().equals(superiorIdentity.getType())
                            && superiorIdentity.getPartnerExpireTime() != null
                            && superiorIdentity.getPartnerExpireTime().after(new Date())) {
                        //上上级合伙人获得10%团队业绩奖励
                        BigDecimal superiorCommission = item.getPayAmount().multiply(new BigDecimal(config.get(HipoConfigEnum.SHAREHOLDER_GROUP_COMMISSION_RATE.getConfig()))).setScale(2, BigDecimal.ROUND_HALF_UP);
                        commissions.add(build(superiorIdentity.getUserId(), user.getId(), superiorCommission, UserCommissionTypeEnum.SHAREHOLDER_GROUP_COMMISSION, calendar, item.getPayAmount(), IdentityTypeEnum.PARTNER.getType(), item.getId(), item.getProductName(), IdentityTypeEnum.MEMBER.getType()));
                    }
                }


                //找到上级最近的小店或运营中心5%嗨币
                Long superiorPartner = getSuperiorPartner(user.getId());
                if (HIPO_USER_ID != superiorPartner) {
                    BigDecimal addCardPoint = item.getPayAmount().multiply(new BigDecimal(config.get(HipoConfigEnum.PARTNER_SHAREHOLDER_RECOMMEND_MEMBER_RATE.getConfig())));
                    User superiorPartnerUser = userMapper.selectByPrimaryKey(superiorPartner);
                    BigDecimal cardPoint = superiorPartnerUser.getCardPoint().add(addCardPoint);
                    userMapper.updateCardPointById(cardPoint, superiorPartnerUser.getId());
                    cardFlowMapper.insert(CardFlow.builder()
                            .userId(superiorPartnerUser.getId())
                            .amount(addCardPoint)
                            .tradeType(CardTradeTypeEnum.DIRECT_CARD_POINT_REWARD.getTradeType())
                            .type(CardTradeTypeEnum.DIRECT_CARD_POINT_REWARD.getType())
                            .cardPoint(cardPoint)
                            .relateId(item.getId())
                            .remark("最近上级小店或运营中心直推会员嗨币")
                            .createdAt(new Date())
                            .build());
                }


                //好物推荐官直推会员获得5%
                if (MemberStateEnum.LOW.getType().equals(identity.getMemberState())) {
                    BigDecimal addCardPoint = item.getPayAmount().multiply(new BigDecimal(config.get(HipoConfigEnum.RECOMMEND_RECOMMEND_MEMBER_RATE.getConfig())));
                    User superiorRecommendUser = userMapper.selectByPrimaryKey(identity.getUserId());
                    BigDecimal cardPoint = superiorRecommendUser.getCardPoint().add(addCardPoint);
                    userMapper.updateCardPointById(cardPoint, superiorRecommendUser.getId());
                    cardFlowMapper.insert(CardFlow.builder()
                            .userId(superiorRecommendUser.getId())
                            .amount(addCardPoint)
                            .tradeType(CardTradeTypeEnum.DIRECT_CARD_POINT_REWARD.getTradeType())
                            .type(CardTradeTypeEnum.DIRECT_CARD_POINT_REWARD.getType())
                            .cardPoint(cardPoint)
                            .relateId(item.getId())
                            .remark("好物推荐官直推会员嗨币")
                            .createdAt(new Date())
                            .build());
                }

            }

            // 原版  合伙人或运营中心直推
            // MEMBER((byte) 0, "会员")
            // PARTNER((byte) 1, "合伙人")       // 小店
            // SHAREHOLDER((byte) 2, "运营中心") //  联合创始人
            // 先版  运营中心改版为联合创始人
            if (isPartnerSpu || isShareholderSpu) {
                Identity identity = getSuperiorIdentity(item.getUserId());
                if (isPartnerSpu) {
                    if (identity != null) {
                        //合伙人直推合伙人
                        if (IdentityTypeEnum.PARTNER.getType().equals(identity.getType())
                                && identity.getPartnerExpireTime() != null
                                && identity.getPartnerExpireTime().after(new Date())) {
                            // 上级合伙人得40%的直推佣金
                            BigDecimal commission = item.getPayAmount().multiply(new BigDecimal(config.get(HipoConfigEnum.PARTNER_RECOMMEND_PARTNER_COMMISSION_RATE.getConfig()))).setScale(2, BigDecimal.ROUND_HALF_UP);
                            commissions.add(build(identity.getUserId(), user.getId(), commission, UserCommissionTypeEnum.PARTNER_RECOMMEND_PARTNER_COMMISSION, calendar, item.getPayAmount(), IdentityTypeEnum.PARTNER.getType(), item.getId(), item.getProductName(), IdentityTypeEnum.MEMBER.getType()));
                        }

                        //会员直推合伙人
                        if (IdentityTypeEnum.MEMBER.getType().equals(identity.getType())
                                && MemberStateEnum.SUPER.getType().equals(identity.getMemberState())
                                && identity.getMemberExpireTime() != null
                                && identity.getMemberExpireTime().after(new Date())) {

                            Identity superiorIdentity = getSuperiorIdentity(identity.getUserId());
                            if (superiorIdentity != null
                                    && IdentityTypeEnum.PARTNER.getType().equals(superiorIdentity.getType())
                                    && superiorIdentity.getPartnerExpireTime() != null
                                    && superiorIdentity.getPartnerExpireTime().after(new Date())) {
                                //上上级合伙人获得10%团队业绩奖励
                                BigDecimal superiorCommission = item.getPayAmount().multiply(new BigDecimal(config.get(HipoConfigEnum.SHAREHOLDER_GROUP_COMMISSION_RATE.getConfig()))).setScale(2, BigDecimal.ROUND_HALF_UP);
                                commissions.add(build(superiorIdentity.getUserId(), user.getId(), superiorCommission, UserCommissionTypeEnum.SHAREHOLDER_GROUP_COMMISSION, calendar, item.getPayAmount(), IdentityTypeEnum.PARTNER.getType(), item.getId(), item.getProductName(), IdentityTypeEnum.MEMBER.getType()));
                            }
                        }
                    }

                    //找到上级最近的小店和运营中心5%嗨币
                    Long superiorPartner = getSuperiorPartner(user.getId());
                    if (HIPO_USER_ID != superiorPartner) {
                        BigDecimal addCardPoint = item.getPayAmount().multiply(new BigDecimal(config.get(HipoConfigEnum.PARTNER_SHAREHOLDER_RECOMMEND_PARTNER_RATE.getConfig())));
                        User superiorPartnerUser = userMapper.selectByPrimaryKey(superiorPartner);
                        BigDecimal cardPoint = superiorPartnerUser.getCardPoint().add(addCardPoint);
                        userMapper.updateCardPointById(cardPoint, superiorPartnerUser.getId());
                        // 如果有上级   则给上级增加嗨币
                        cardFlowMapper.insert(CardFlow.builder()
                                .userId(superiorPartnerUser.getId())
                                .amount(addCardPoint)
                                .tradeType(CardTradeTypeEnum.CO_FOUNDER_HI_COIN_REBATE_ADD.getTradeType())
                                .type(CardTradeTypeEnum.CO_FOUNDER_HI_COIN_REBATE_ADD.getType())
                                .cardPoint(cardPoint)
                                .relateId(item.getId())
                                .remark("小店或运营中心直推嗨币")
                                .createdAt(new Date())
                                .build());
                        // 查找联合创始人上级
                        UserRelationship userRelationship = userRelationshipMapper.findOneBySubordinateId(user.getId());
                        if (userRelationship != null) {
                            // 计算给上级发放的佣金金额
                            extracted(config, item, userRelationship);
                        }
                    }
                }

                if (isShareholderSpu) {
                    //找到上级最近的小店和运营中心5%嗨币
                    Long superiorShareholder = getSuperiorShareholder(user.getId());
                    if (HIPO_USER_ID != superiorShareholder) {
                        BigDecimal addCardPoint = item.getPayAmount().multiply(new BigDecimal(config.get(HipoConfigEnum.SHAREHOLDER_RECOMMEND_SHAREHOLDER_RATE.getConfig())));
                        User superiorShareholderUser = userMapper.selectByPrimaryKey(superiorShareholder);
                        BigDecimal cardPoint = superiorShareholderUser.getCardPoint().add(addCardPoint);
                        userMapper.updateCardPointById(cardPoint, superiorShareholderUser.getId());
                        cardFlowMapper.insert(CardFlow.builder()
                                .userId(superiorShareholderUser.getId())
                                .amount(addCardPoint)
                                .tradeType(CardTradeTypeEnum.CO_FOUNDER_HI_COIN_REBATE_ADD.getTradeType())
                                .type(CardTradeTypeEnum.CO_FOUNDER_HI_COIN_REBATE_ADD.getType())
                                .cardPoint(cardPoint)
                                .relateId(item.getId())
                                .remark("小店或运营中心直推嗨币")
                                .createdAt(new Date())
                                .build());
                        // 查找联合创始人上级
                        UserRelationship userRelationship = userRelationshipMapper.findOneBySubordinateId(user.getId());
                        if (userRelationship != null) {
                            extracted(config, item, userRelationship);
                        }
                    }
                }
            }

            //选品商城商品
            if (isStoreSpu) {
                Identity identity = getSuperiorIdentity(item.getUserId());
                if (identity != null
                        && IdentityTypeEnum.PARTNER.getType().equals(identity.getType())
                        && identity.getPartnerExpireTime() != null
                        && identity.getPartnerExpireTime().after(new Date())) {
                    Identity currentIdentity = identityMapper.findOneByUserId(user.getId());

                    if (IdentityTypeEnum.PARTNER.getType() > currentIdentity.getType()) {
                        //上级合伙人获得 销售价-小店价
                        Sku sku = skuMap.get(item.getSkuId());
                        BigDecimal commission = (item.getPrice().subtract(sku.getPartnerPrice())).multiply(new BigDecimal(item.getCount()));
                        commissions.add(build(identity.getUserId(), user.getId(), commission, UserCommissionTypeEnum.PARTNER_SPU_COMMISSION, calendar, item.getPayAmount(), IdentityTypeEnum.PARTNER.getType(), item.getId(), item.getProductName(), IdentityTypeEnum.MEMBER.getType()));
                    }


                    if (IdentityTypeEnum.PARTNER.getType().equals(currentIdentity.getType())
                            && currentIdentity.getPartnerExpireTime() != null
                            && currentIdentity.getPartnerExpireTime().after(new Date())) {
                        //购买人是合伙人 上级合伙人获得2%业绩收入 todo
                        BigDecimal commission = item.getPayAmount().multiply(new BigDecimal(config.get(HipoConfigEnum.PARTNER_PURCHASE_RATE.getConfig()))).setScale(2, BigDecimal.ROUND_HALF_UP);
                        commissions.add(build(identity.getUserId(), user.getId(), commission, UserCommissionTypeEnum.PARTNER_PURCHASE_COMMISSION, calendar, item.getPayAmount(), IdentityTypeEnum.PARTNER.getType(), item.getId(), item.getProductName(), IdentityTypeEnum.MEMBER.getType()));
                    }
                }
            }
            //登记会员以上团队业绩
            createGroupPerformance(item, config);
        }

        //使用了VIP佣金机会不发放区域代理佣金
        if (!useCommissionCount) {
            // 发放省市区佣金
            commissions.addAll(prepareCourierCommission(orderSkuVOList.get(0).getOrderId(), orderSkuVOList, spuMap));
        }


        if (!commissions.isEmpty()) {
            userCommissionMapper.batchInsert(commissions);
        }
    }

    private void extracted(Map<String, String> config, OrderSkuVO item, UserRelationship userRelationship) {
        // 计算给上级发放的佣金金额
        BigDecimal rebate = new BigDecimal(config.get(HipoConfigEnum.SHAREHOLDER_COMMISSION_RATE.getConfig()));
        BigDecimal cardRebate = item.getPayAmount().multiply(rebate).setScale(0, BigDecimal.ROUND_UP);
        if (cardRebate.compareTo(BigDecimal.ZERO) > 0) {
            // 设置冻结时间
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.DATE, 15);
            userCommissionMapper.insert(UserCommission.builder()
                    .superiorId(userRelationship.getSuperiorId())
                    .subordinateId(userRelationship.getSubordinateId())
                    .orderSkuId(item.getId())
                    .commission(cardRebate)
                    .type(UserCommissionTypeEnum.CO_FOUNDER_DIRECT_PUSH_REBATE.getType())
                    .freezeTime(cal.getTime())
                    .status(UserCommissionStatusEnum.FREEZE.getStatus())
                    .relateId(item.getSpuId())
                    .remark(UserCommissionTypeEnum.CO_FOUNDER_DIRECT_PUSH_REBATE.getRemark())
                    .createdAt(new Date())
                    .updatedAt(new Date())
                    .amount(item.getPayAmount())
                    .identityType((byte) -1)
                    .businessType(UserCommissionBusinessTypeEnum.USER.getType())
                    .build());
        }
    }

    private BigDecimal getCardPointRate(Identity identity, Map<String, String> config) {
        BigDecimal rate = BigDecimal.ZERO;
        if (UserLevelEnum.MEMBER_L1.getLevel().equals(identity.getMemberLevel())) {
            rate = new BigDecimal(config.get(HipoConfigEnum.DIRECT_CARD_POINT_V1_RATE.getConfig()));
        } else if (UserLevelEnum.MEMBER_L2.getLevel().equals(identity.getMemberLevel())) {
            rate = new BigDecimal(config.get(HipoConfigEnum.DIRECT_CARD_POINT_V2_RATE.getConfig()));
        } else {
            rate = new BigDecimal(config.get(HipoConfigEnum.DIRECT_CARD_POINT_V3_RATE.getConfig()));
        }
        return rate;
    }


    public void createGroupPerformance(OrderSku orderSku, Map<String, String> config) {
        Map<Long, Boolean> map = new HashMap<>();
        Long sub = orderSku.getUserId();
        boolean keepRun = true;
        int sorts = 0;
        do {
            // 如果已经存在，说明进入循环了
            if (!map.containsKey(sub)) {
                map.put(sub, true);
                UserRelationship userRelationship = userRelationshipMapper.findOneBySubordinateId(sub);
                if (userRelationship != null) {
                    Identity superIdentity = identityMapper.findOneByUserId(userRelationship.getSuperiorId());
                    // 会员以上就有团队累积
                    if (superIdentity != null && superIdentity.getMemberState().equals(MemberStateEnum.SUPER.getType())) {
                        sorts = sorts + 1;
                        // 增加团队业绩
                        groupsPerformanceMapper.insert(GroupsPerformance.builder()
                                .userId(userRelationship.getSuperiorId())
                                .orderSkuId(orderSku.getId())
                                .performance(orderSku.getPayAmount())
                                .status(GroupsPerformanceStatusEnum.NOT_COUNT.getStatus())
                                .createdAt(new Date())
                                .updatedAt(new Date())
                                .sorts(sorts)
                                .build());

                        BigDecimal sum = groupsPerformanceMapper.sumByUserId(superIdentity.getUserId());
                        if (sum != null) {
                            if (sum.compareTo(BigDecimal.valueOf(10000000)) >= 0 && superIdentity.getMemberLevel() < UserLevelEnum.MEMBER_L4.getLevel()) {
                                // 如果达到千万，并且会员等级小于4，则升级到4
                                superIdentity.setMemberLevel(UserLevelEnum.MEMBER_L4.getLevel());
                                if (superIdentity.getLevel() < UserLevelEnum.MEMBER_L4.getLevel()) {
                                    superIdentity.setLevel(UserLevelEnum.MEMBER_L4.getLevel());
                                    levelService.updateUserLevel(superIdentity.getUserId(), UserLevelEnum.MEMBER_L4.getLevel());
                                }
                                identityMapper.updateByPrimaryKeySelective(superIdentity);
                            } else if (sum.compareTo(BigDecimal.valueOf(1000000)) >= 0 && superIdentity.getMemberLevel() < UserLevelEnum.MEMBER_L3.getLevel()) {
                                // 如果达到百万，并且会员等级小于4，则升级到4
                                superIdentity.setMemberLevel(UserLevelEnum.MEMBER_L3.getLevel());
                                if (superIdentity.getLevel() < UserLevelEnum.MEMBER_L3.getLevel()) {
                                    superIdentity.setLevel(UserLevelEnum.MEMBER_L3.getLevel());
                                    levelService.updateUserLevel(superIdentity.getUserId(), UserLevelEnum.MEMBER_L3.getLevel());
                                }
                                identityMapper.updateByPrimaryKeySelective(superIdentity);
                            } else if (sum.compareTo(BigDecimal.valueOf(100000)) >= 0 && superIdentity.getMemberLevel() < UserLevelEnum.MEMBER_L2.getLevel()) {
                                // 如果达到十万，并且会员等级小于4，则升级到4
                                superIdentity.setMemberLevel(UserLevelEnum.MEMBER_L2.getLevel());
                                if (superIdentity.getLevel() < UserLevelEnum.MEMBER_L2.getLevel()) {
                                    superIdentity.setLevel(UserLevelEnum.MEMBER_L2.getLevel());
                                    levelService.updateUserLevel(superIdentity.getUserId(), UserLevelEnum.MEMBER_L2.getLevel());
                                }
                                identityMapper.updateByPrimaryKeySelective(superIdentity);
                            }
                        }
                    }
                    sub = userRelationship.getSuperiorId();
                } else {
                    keepRun = false;
                }
            } else {
                keepRun = false;
            }
        } while (keepRun);
    }

    public void createPartnerPerformance(OrderSku orderSku, Identity superiorIdentity) {

        // 10、【这里仅合伙人才有】O直推A，A直推B，B直推C，C直推D1：
        //（1）当C直推D1时，A得5%的感恩奖佣金，A得2000元的团队业绩累积。
        //（2）当C直推D2时，B得5%的感恩奖佣金，B得2000元的团队业绩累积。
        //（3）当C直推D3时，B得5%的感恩奖佣金，B得2000元的团队业绩累积。

        // 先获取最近的合伙人identity
        if (superiorIdentity != null) {
            // 判断C是否为首次推荐
            Long count = userRelationshipMapper.countBySuperiorIdAndStatus(superiorIdentity.getUserId(), RelationshipStatusEnum.BIND.getStatus());
            Long supId = null;
            if (count != null && count.equals(1L)) {
                //首次推荐
                // 找C上上级A
                UserRelationship u1 = userRelationshipMapper.findOneBySubordinateId(superiorIdentity.getUserId());
                if (u1 != null) {
                    UserRelationship u2 = userRelationshipMapper.findOneBySubordinateId(u1.getSuperiorId());
                    if (u2 != null) {
                        supId = u2.getSuperiorId();
                    }
                }
            }
            if (count != null && count > 1) {
                //非首次
                // 找C上级B
                UserRelationship u1 = userRelationshipMapper.findOneBySubordinateId(superiorIdentity.getUserId());
                if (u1 != null) {
                    supId = u1.getSuperiorId();
                }
            }
            if (supId != null) {
                // 如果是合伙人，5%的感恩奖佣金，2000元的团队业绩累积
                Identity identity = identityMapper.findOneByUserId(supId);
                if (identity != null && identity.getPartnerLevel() >= UserLevelEnum.PARTNER_L1.getLevel()) {
                    // 设置冻结时间
                    Calendar calendar = Calendar.getInstance();
                    calendar.add(Calendar.DATE, 7);

                    userCommissionMapper.insert(build(identity.getUserId(), orderSku.getUserId(), orderSku.getPayAmount().multiply(new BigDecimal(0.05)).setScale(2, BigDecimal.ROUND_HALF_DOWN), UserCommissionTypeEnum.THANKFUL_COMMISSION, calendar, orderSku.getPayAmount(), IdentityTypeEnum.PARTNER.getType(), orderSku.getId(), orderSku.getProductName(), IdentityTypeEnum.PARTNER.getType()));

                    shareholderPerformanceMapper.insert(ShareholderPerformance.builder()
                            .userId(identity.getUserId())
                            .orderSkuId(orderSku.getId())
                            .performance(orderSku.getPayAmount())
                            .commission(BigDecimal.ZERO)
                            .status(ShareholderPerformanceStatusEnum.NOT_COUNT.getStatus())
                            .type(PartnerTypeEnum.L2.getType())
                            .createdAt(new Date())
                            .updatedAt(new Date())
                            .build());
                }
            }
        }
    }


    @Override
    public void deductAddPerformance(List<OrderSkuVO> orderSkuList) {
        Map<Long, Spu> spuMap = daoService.getSpuMap(orderSkuList.stream().map(OrderSkuVO::getSpuId).collect(Collectors.toList()));
        Map<String, String> config = daoService.getHipoConfigMap();
        String memberSpu = config.get(HipoConfigEnum.MEMBER_SPU.getConfig());
        BigDecimal amount = BigDecimal.ZERO;
        for (OrderSkuVO item : orderSkuList) {
            boolean isMemberSpu = item.getSpuId().equals(Long.valueOf(memberSpu));
            boolean isOrdinarySpu = SpuTypeEnum.ORDINARY.getType().equals(spuMap.get(item.getSpuId()).getType());
            boolean isCommissionSpu = SpuTypeEnum.COMMISSION.getType().equals(spuMap.get(item.getSpuId()).getType());
            if (isCommissionSpu || (isOrdinarySpu && isMemberSpu)) {
                amount = amount.add(item.getPayAmount());
            }
        }

        PerformanceAmount performanceAmount = performanceAmountMapper.selectByPrimaryKey(PerformanceIdEnum.MEMBER_INVITE.getId());
        performanceAmount.setPerformance(performanceAmount.getPerformance().subtract(amount));
        performanceAmount.setHistoryPerformance(performanceAmount.getHistoryPerformance().subtract(amount));
        performanceAmount.setUpdatedAt(new Date());
        performanceAmountMapper.updateByPrimaryKeySelective(performanceAmount);
    }

    @Override
    public void deductAddPerformance(Spu spu, BigDecimal refundAmount) {
        Map<String, String> config = daoService.getHipoConfigMap();
        String memberSpu = config.get(HipoConfigEnum.MEMBER_SPU.getConfig());
        boolean isMemberSpu = spu.getId().equals(Long.valueOf(memberSpu));
        boolean isOrdinarySpu = SpuTypeEnum.ORDINARY.getType().equals(spu.getType());
        boolean isCommissionSpu = SpuTypeEnum.COMMISSION.getType().equals(spu.getType());
        if (isCommissionSpu || (isOrdinarySpu && isMemberSpu)) {
            PerformanceAmount performanceAmount = performanceAmountMapper.selectByPrimaryKey(PerformanceIdEnum.MEMBER_INVITE.getId());
            performanceAmount.setPerformance(performanceAmount.getPerformance().subtract(refundAmount));
            performanceAmount.setHistoryPerformance(performanceAmount.getHistoryPerformance().subtract(refundAmount));
            performanceAmount.setUpdatedAt(new Date());
            performanceAmountMapper.updateByPrimaryKeySelective(performanceAmount);
        }
    }

    //发放活动补贴奖励
    public List<UserCommission> prepareStaticDividend(List<UserCommission> commissions, Long userId, BigDecimal
            amount, Calendar calendar, Long orderSkuId, String remark, Map<String, String> config, Long
                                                              dividendPrecipitationId) {
        BigDecimal memberLimit = new BigDecimal(config.get(HipoConfigEnum.MEMBER_STATIC_DIVIDEND_LIMIT.getConfig()));
        BigDecimal partnerLimit = new BigDecimal(config.get(HipoConfigEnum.PARTNER_STATIC_DIVIDEND_LIMIT.getConfig()));
        BigDecimal shareholderLimit = new BigDecimal(config.get(HipoConfigEnum.SHAREHOLDER_STATIC_DIVIDEND_LIMIT.getConfig()));
        List<Identity> memberList = identityMapper.findAllStaticDividendMember(IdentityTypeEnum.MEMBER.getType(), MemberStateEnum.SUPER.getType(), memberLimit, new Date());
        List<Identity> partnerList = identityMapper.findAllStaticDividendPartner(IdentityTypeEnum.PARTNER.getType(), partnerLimit, new Date());
        List<Identity> shareholderList = identityMapper.findAllStaticDividendShareholder(IdentityTypeEnum.SHAREHOLDER.getType(), shareholderLimit, new Date());

        //计算平均分红
        BigDecimal dividendAmount = amount.multiply(new BigDecimal(config.get(HipoConfigEnum.STATIC_DIVIDEND.getConfig())));
        Integer divideCount = memberList.size() + partnerList.size() + shareholderList.size();
        BigDecimal avgAividend = BigDecimal.ZERO;
        if (divideCount > 0) {
            avgAividend = dividendAmount.divide(new BigDecimal(divideCount), 2, BigDecimal.ROUND_HALF_UP);
        }

        BigDecimal finalAvgAividend = avgAividend;
        memberList.stream().forEach(item -> {
            BigDecimal staticDividend = finalAvgAividend;
            if (memberLimit.subtract(item.getStaticDividend()).compareTo(finalAvgAividend) < 0) {
                staticDividend = memberLimit.subtract(item.getStaticDividend());
            }
            commissions.add(buildIssued(item.getUserId(), userId, staticDividend, UserCommissionTypeEnum.STATIC_DIVIDEND, amount, item.getType(), orderSkuId, remark));
            identityMapper.updateStaticDividendById(item.getStaticDividend().add(staticDividend), item.getId());
        });
        partnerList.stream().forEach(item -> {
            BigDecimal staticDividend = finalAvgAividend;
            if (partnerLimit.subtract(item.getStaticDividend()).compareTo(finalAvgAividend) < 0) {
                staticDividend = partnerLimit.subtract(item.getStaticDividend());
            }
            commissions.add(buildIssued(item.getUserId(), userId, staticDividend, UserCommissionTypeEnum.STATIC_DIVIDEND, amount, item.getType(), orderSkuId, remark));
            identityMapper.updateStaticDividendById(item.getStaticDividend().add(staticDividend), item.getId());
        });
        shareholderList.stream().forEach(item -> {
            BigDecimal staticDividend = finalAvgAividend;
            if (shareholderLimit.subtract(item.getStaticDividend()).compareTo(finalAvgAividend) < 0) {
                staticDividend = shareholderLimit.subtract(item.getStaticDividend());
            }
            commissions.add(buildIssued(item.getUserId(), userId, staticDividend, UserCommissionTypeEnum.STATIC_DIVIDEND, amount, item.getType(), orderSkuId, remark));
            identityMapper.updateStaticDividendById(item.getStaticDividend().add(staticDividend), item.getId());
        });

        dividendPrecipitationMapper.updateDividendCountAndUpdatedAtById(divideCount, new Date(), dividendPrecipitationId);
        return commissions;
    }

    @Override
    public void editDividendPrecipitation(Byte type, BigDecimal amount, Integer
            count, Map<String, String> config) {
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        if (DividendPrecipitationTypeEnum.DIRECTOR.getType().equals(type)) {
            calendar.set(Calendar.DAY_OF_MONTH, 1);
        } else {
            calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        }
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.HOUR_OF_DAY, 0);

        BigDecimal commission = BigDecimal.ZERO;
        if (DividendPrecipitationTypeEnum.MEMBER.getType().equals(type)) {
            BigDecimal rate = new BigDecimal(config.get(HipoConfigEnum.MEMBER_DIVIDENDS_1_RATE.getConfig())).add(new BigDecimal(config.get(HipoConfigEnum.MEMBER_DIVIDENDS_2_RATE.getConfig()))).add(new BigDecimal(config.get(HipoConfigEnum.MEMBER_DIVIDENDS_3_RATE.getConfig())));
            commission = amount.multiply(rate);
        } else if (DividendPrecipitationTypeEnum.PARTNER.getType().equals(type)) {
            BigDecimal rate = new BigDecimal(config.get(HipoConfigEnum.PARTNER_DIVIDENDS_1_RATE.getConfig())).add(new BigDecimal(config.get(HipoConfigEnum.PARTNER_DIVIDENDS_2_RATE.getConfig()))).add(new BigDecimal(config.get(HipoConfigEnum.PARTNER_DIVIDENDS_3_RATE.getConfig())));
            commission = amount.multiply(rate);
        } else if (DividendPrecipitationTypeEnum.SHAREHOLDER.getType().equals(type)) {
            BigDecimal rate = new BigDecimal(config.get(HipoConfigEnum.SHAREHOLDER_DIVIDENDS_1_RATE.getConfig())).add(new BigDecimal(config.get(HipoConfigEnum.SHAREHOLDER_DIVIDENDS_2_RATE.getConfig()))).add(new BigDecimal(config.get(HipoConfigEnum.SHAREHOLDER_DIVIDENDS_3_RATE.getConfig())));
            commission = amount.multiply(rate);
        } else if (DividendPrecipitationTypeEnum.MARKET_SUBSIDY.getType().equals(type)) {
            commission = amount.multiply(new BigDecimal(config.get(HipoConfigEnum.STATIC_DIVIDEND.getConfig())));
        } else if (DividendPrecipitationTypeEnum.DIRECTOR.getType().equals(type)) {
            commission = amount.multiply(new BigDecimal(config.get(HipoConfigEnum.DIRECTOR_COMMISSION_RATE.getConfig())));
        } else if (DividendPrecipitationTypeEnum.DIRECTOR.getType().equals(type)) {
            commission = amount.multiply(new BigDecimal(config.get(HipoConfigEnum.SHAREHOLDER_COMPANY_DIVIDENDS_RATE.getConfig())));
        }
        DividendPrecipitation weekDividend = dividendPrecipitationMapper.findOneByTypeAndWeekTime(type, calendar.getTime());
        if (weekDividend == null) {
            dividendPrecipitationMapper.insert(DividendPrecipitation.builder()
                    .type(type)
                    .count(count)
                    .amount(amount)
                    .commission(commission)
                    .weekTime(calendar.getTime())
                    .status(DividendPrecipitationStatusEnum.NOT_GIVE.getStatus())
                    .updatedAt(new Date())
                    .dividendCount(0)
                    .build());
        } else {
            dividendPrecipitationMapper.updateDividendPrecipitation(count, amount, commission, new Date(), weekDividend.getId());
        }

    }

    @Override
    public void rewardDividendPrecipitation() {
        Map<String, String> config = daoService.getHipoConfigMap();
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -7);
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        Date lastWeek = calendar.getTime();

        //获取之前未发放周 不包括本周
        List<DividendPrecipitation> dividendPrecipitations = dividendPrecipitationMapper.findNotGiveWeek(lastWeek, DividendPrecipitationStatusEnum.NOT_GIVE.getStatus());

        List<UserCommission> commissions = new ArrayList<>();
        if (dividendPrecipitations.size() > 0) {
            dividendPrecipitations.stream().forEach(item -> {
                if (DividendPrecipitationTypeEnum.MEMBER.getType().equals(item.getType())) {
                    if (item.getAmount().compareTo(BigDecimal.ZERO) >= 0) {
                        issueMemberDividends(commissions, HIPO_USER_ID, item.getAmount(), Calendar.getInstance(), null, "分红", config);
                    } else {
                        //发放周金额为负数 就添加到本周
                        calendar.add(Calendar.DATE, 7);
                        Date currentWeek = calendar.getTime();
                        DividendPrecipitation weekDividendPrecipitation = dividendPrecipitationMapper.findOneByTypeAndStatusAndWeekTime(DividendPrecipitationTypeEnum.MEMBER.getType(), DividendPrecipitationStatusEnum.NOT_GIVE.getStatus(), currentWeek);
                        if (weekDividendPrecipitation != null) {
                            dividendPrecipitationMapper.updateDividendPrecipitation(item.getCount(), item.getAmount(), item.getCommission(), new Date(), weekDividendPrecipitation.getId());
                        } else {
                            dividendPrecipitationMapper.insert(DividendPrecipitation.builder()
                                    .type(DividendPrecipitationTypeEnum.MEMBER.getType())
                                    .count(item.getCount())
                                    .amount(item.getAmount())
                                    .commission(item.getCommission())
                                    .weekTime(currentWeek)
                                    .status(DividendPrecipitationStatusEnum.NOT_GIVE.getStatus())
                                    .updatedAt(new Date())
                                    .dividendCount(0)
                                    .build());
                        }
                    }
                }
            });

            if (!commissions.isEmpty()) {
                userCommissionMapper.batchInsert(commissions);
                dividendPrecipitationMapper.updateStatusAndUpdatedAtByWeekTimeBeforeAndTypeAndStatus(DividendPrecipitationStatusEnum.GIVE.getStatus(), new Date(), lastWeek, DividendPrecipitationTypeEnum.MEMBER.getType(), DividendPrecipitationStatusEnum.NOT_GIVE.getStatus());
            }
        }
    }

    @Override
    public void rewardMarketSubsidy() {
        List<UserCommission> commissions = new ArrayList<>();
        Map<String, String> config = daoService.getHipoConfigMap();
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -7);
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        Date lastWeek = calendar.getTime();
        DividendPrecipitation dividendPrecipitation = dividendPrecipitationMapper.findOneByTypeAndStatusAndWeekTime(DividendPrecipitationTypeEnum.MARKET_SUBSIDY.getType(), DividendPrecipitationStatusEnum.NOT_GIVE.getStatus(), lastWeek);

        if (dividendPrecipitation != null) {
            if (dividendPrecipitation.getAmount().compareTo(BigDecimal.ZERO) >= 0) {
                prepareStaticDividend(commissions, HIPO_USER_ID, dividendPrecipitation.getAmount(), Calendar.getInstance(), null, "活动补贴", config, dividendPrecipitation.getId());
            } else {
                //发放金额为负数 就添加到下一周
                calendar.add(Calendar.DATE, 7);
                Date currentWeek = calendar.getTime();
                DividendPrecipitation weekDividendPrecipitation = dividendPrecipitationMapper.findOneByTypeAndStatusAndWeekTime(DividendPrecipitationTypeEnum.MARKET_SUBSIDY.getType(), DividendPrecipitationStatusEnum.NOT_GIVE.getStatus(), currentWeek);
                if (weekDividendPrecipitation != null) {
                    dividendPrecipitationMapper.updateDividendPrecipitation(dividendPrecipitation.getCount(), dividendPrecipitation.getAmount(), dividendPrecipitation.getCommission(), new Date(), weekDividendPrecipitation.getId());
                } else {
                    dividendPrecipitationMapper.insert(DividendPrecipitation.builder()
                            .type(DividendPrecipitationTypeEnum.MEMBER.getType())
                            .count(dividendPrecipitation.getCount())
                            .amount(dividendPrecipitation.getAmount())
                            .commission(dividendPrecipitation.getCommission())
                            .weekTime(currentWeek)
                            .status(DividendPrecipitationStatusEnum.NOT_GIVE.getStatus())
                            .updatedAt(new Date())
                            .dividendCount(0)
                            .build());
                }
            }

            if (!commissions.isEmpty()) {
                userCommissionMapper.batchInsert(commissions);
                dividendPrecipitationMapper.updateStatusAndUpdatedAtByWeekTimeAndType(DividendPrecipitationStatusEnum.GIVE.getStatus(), new Date(), lastWeek, DividendPrecipitationTypeEnum.MARKET_SUBSIDY.getType());
            }
        }
    }

    @Override
    public void rewardDirectorCommission() {
        List<UserCommission> commissions = new ArrayList<>();
        Map<String, String> config = daoService.getHipoConfigMap();
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, -1);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        Date lastMonth = calendar.getTime();

        DividendPrecipitation dividendPrecipitation = dividendPrecipitationMapper.findOneByTypeAndStatusAndWeekTime(DividendPrecipitationTypeEnum.DIRECTOR.getType(), DividendPrecipitationStatusEnum.NOT_GIVE.getStatus(), lastMonth);
        if (dividendPrecipitation != null) {
            if (dividendPrecipitation.getAmount().compareTo(BigDecimal.ZERO) >= 0) {
                prepareDirectorCommission(commissions, HIPO_USER_ID, dividendPrecipitation.getAmount(), Calendar.getInstance(), null, "联合创始人分红", config, dividendPrecipitation.getId());
            } else {
                //发放金额为负数 就添加到下一月
                calendar.add(Calendar.MONTH, 1);
                Date currentMonth = calendar.getTime();
                DividendPrecipitation weekDividendPrecipitation = dividendPrecipitationMapper.findOneByTypeAndStatusAndWeekTime(DividendPrecipitationTypeEnum.DIRECTOR.getType(), DividendPrecipitationStatusEnum.NOT_GIVE.getStatus(), currentMonth);
                if (weekDividendPrecipitation != null) {
                    dividendPrecipitationMapper.updateDividendPrecipitation(dividendPrecipitation.getCount(), dividendPrecipitation.getAmount(), dividendPrecipitation.getCommission(), new Date(), weekDividendPrecipitation.getId());
                } else {
                    dividendPrecipitationMapper.insert(DividendPrecipitation.builder()
                            .type(DividendPrecipitationTypeEnum.DIRECTOR.getType())
                            .count(dividendPrecipitation.getCount())
                            .amount(dividendPrecipitation.getAmount())
                            .commission(dividendPrecipitation.getCommission())
                            .weekTime(currentMonth)
                            .status(DividendPrecipitationStatusEnum.NOT_GIVE.getStatus())
                            .updatedAt(new Date())
                            .dividendCount(0)
                            .build());
                }
            }

            if (!commissions.isEmpty()) {
                userCommissionMapper.batchInsert(commissions);
                dividendPrecipitationMapper.updateStatusAndUpdatedAtByWeekTimeAndType(DividendPrecipitationStatusEnum.GIVE.getStatus(), new Date(), lastMonth, DividendPrecipitationTypeEnum.DIRECTOR.getType());
            }
        }
    }

    private void prepareDirectorCommission(List<UserCommission> commissions, long userId, BigDecimal
            amount, Calendar calendar, Long orderSkuId, String remark, Map<String, String> config, Long id) {

        List<Identity> director = identityMapper.findAllByDirector(ToggleEnum.ON.getStatus());

        //计算平均分红
        BigDecimal dividendAmount = amount.multiply(new BigDecimal(config.get(HipoConfigEnum.DIRECTOR_COMMISSION_RATE.getConfig())));
        //
        Integer divideCount = DIRECTOR_COUNT;
        BigDecimal avgAividend = BigDecimal.ZERO;
        if (divideCount > 0) {
            avgAividend = dividendAmount.divide(new BigDecimal(divideCount), 2, BigDecimal.ROUND_HALF_UP);
        }

        BigDecimal finalAvgAividend = avgAividend;
        director.stream().forEach(item -> {
            BigDecimal staticDividend = finalAvgAividend;
            commissions.add(buildIssued(item.getUserId(), userId, staticDividend, UserCommissionTypeEnum.DIRECTOR_COMMISSION, amount, item.getType(), orderSkuId, remark));
        });

        //更新发放的联合创始人
        dividendPrecipitationMapper.updateDividendCountAndUpdatedAtById(divideCount, new Date(), id);
    }

    @Override
    public void rewardShareholderPrecipitation() {
        Map<String, String> config = daoService.getHipoConfigMap();
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -7);
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        Date lastWeek = calendar.getTime();

        //获取之前未发放周 不包括本周
        List<DividendPrecipitation> dividendPrecipitations = dividendPrecipitationMapper.findNotGiveWeekAndType(lastWeek, DividendPrecipitationStatusEnum.NOT_GIVE.getStatus(), DividendPrecipitationTypeEnum.SHAREHOLDER_COMPANY.getType());

        List<UserCommission> commissions = new ArrayList<>();
        if (dividendPrecipitations.size() > 0) {
            dividendPrecipitations.stream().forEach(item -> {
                if (item.getAmount().compareTo(BigDecimal.ZERO) >= 0) {
                    issueShareholderCompanyDividends(commissions, HIPO_USER_ID, item.getAmount(), Calendar.getInstance(), null, null, config);
                } else {
                    //发放周金额为负数 就添加到本周
                    calendar.add(Calendar.DATE, 7);
                    Date currentWeek = calendar.getTime();
                    DividendPrecipitation weekDividendPrecipitation = dividendPrecipitationMapper.findOneByTypeAndStatusAndWeekTime(DividendPrecipitationTypeEnum.SHAREHOLDER_COMPANY.getType(), DividendPrecipitationStatusEnum.NOT_GIVE.getStatus(), currentWeek);
                    if (weekDividendPrecipitation != null) {
                        dividendPrecipitationMapper.updateDividendPrecipitation(item.getCount(), item.getAmount(), item.getCommission(), new Date(), weekDividendPrecipitation.getId());
                    } else {
                        dividendPrecipitationMapper.insert(DividendPrecipitation.builder()
                                .type(DividendPrecipitationTypeEnum.SHAREHOLDER_COMPANY.getType())
                                .count(item.getCount())
                                .amount(item.getAmount())
                                .commission(item.getCommission())
                                .weekTime(currentWeek)
                                .status(DividendPrecipitationStatusEnum.NOT_GIVE.getStatus())
                                .updatedAt(new Date())
                                .dividendCount(0)
                                .build());
                    }
                }
            });

            if (!commissions.isEmpty()) {
                userCommissionMapper.batchInsert(commissions);
                dividendPrecipitationMapper.updateStatusAndUpdatedAtByWeekTimeBeforeAndTypeAndStatus(DividendPrecipitationStatusEnum.GIVE.getStatus(), new Date(), lastWeek, DividendPrecipitationTypeEnum.SHAREHOLDER_COMPANY.getType(), DividendPrecipitationStatusEnum.NOT_GIVE.getStatus());
            }

        }
    }

    public List<UserCommission> issueShareholderCompanyDividends(List<UserCommission> commissions, Long
            userId, BigDecimal amount, Calendar calendar, Long orderSkuId, String remark, Map<String, String> config) {

        Date date = new Date();
        // 获取所有的副总裁、总裁、董事（仅副总裁以上有业绩分红）
        List<IdentitySimpleVO> identityList = identityMapper.findAllShareholderCompanyForDividends(date);
        List<IdentitySimpleVO> identityListOverLevel34 = new ArrayList<>();
        List<IdentitySimpleVO> identityListOverLevel4 = new ArrayList<>();

        identityList.stream().forEach(i -> {
            if (UserLevelEnum.SHAREHOLDER_L3.getLevel().equals(i.getShareholderLevel())) {
                if (i.getL3EffectTime() != null && i.getL3EffectTime().before(date)) {
                    identityListOverLevel34.add(i);
                }
            }
            if (UserLevelEnum.SHAREHOLDER_L4.getLevel().equals(i.getShareholderLevel())) {
                if (i.getL4EffectTime() != null && i.getL4EffectTime().before(date)) {
                    identityListOverLevel4.add(i);
                }
                if (i.getL3EffectTime() != null && i.getL3EffectTime().before(date)) {
                    identityListOverLevel34.add(i);
                }
            }
        });

        if (!identityList.isEmpty()) {
            // 业绩分红
            BigDecimal one = amount
                    .multiply(new BigDecimal(config.get(HipoConfigEnum.SHAREHOLDER_DIVIDENDS_1_RATE.getConfig())))
                    .divide(new BigDecimal(identityList.size()), 2, BigDecimal.ROUND_HALF_UP)
                    .setScale(2, BigDecimal.ROUND_HALF_UP);

            BigDecimal two = identityListOverLevel34.isEmpty() ? BigDecimal.ZERO : amount
                    .multiply(new BigDecimal(config.get(HipoConfigEnum.SHAREHOLDER_DIVIDENDS_2_RATE.getConfig())))
                    .divide(new BigDecimal(identityListOverLevel34.size()), 2, BigDecimal.ROUND_HALF_UP)
                    .setScale(2, BigDecimal.ROUND_HALF_UP);


            BigDecimal three = identityListOverLevel4.isEmpty() ? BigDecimal.ZERO : amount
                    .multiply(new BigDecimal(config.get(HipoConfigEnum.SHAREHOLDER_DIVIDENDS_3_RATE.getConfig())))
                    .divide(new BigDecimal(identityListOverLevel4.size()), 2, BigDecimal.ROUND_HALF_UP)
                    .setScale(2, BigDecimal.ROUND_HALF_UP);

            identityList.stream().forEach(each -> {
                commissions.add(buildIssued(each.getUserId(), userId, one, UserCommissionTypeEnum.SHAREHOLDER_L2_DIVIDENDS, amount, IdentityTypeEnum.SHAREHOLDER.getType(), orderSkuId, remark));
            });

            identityListOverLevel34.stream().forEach(each -> {
                commissions.add(buildIssued(each.getUserId(), userId, two, UserCommissionTypeEnum.SHAREHOLDER_L3_DIVIDENDS, amount, IdentityTypeEnum.SHAREHOLDER.getType(), orderSkuId, remark));
            });

            identityListOverLevel4.stream().forEach(each -> {
                commissions.add(buildIssued(each.getUserId(), userId, three, UserCommissionTypeEnum.SHAREHOLDER_L4_DIVIDENDS, amount, IdentityTypeEnum.SHAREHOLDER.getType(), orderSkuId, remark));
            });
        }

        return commissions;
    }

    @Override
    public void rewardWelfare() {
        //获取平分资格用户
        List<Identity> identityList = identityMapper.findAllByWelfareGreaterThan(BigDecimal.ZERO);
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -1);
        //昨日抢购订单业绩
        BigDecimal yesterdayAmount = orderSkuMapper.sumOrderKindAmount(getFirstTime(calendar).getTime(), getFirstTime(Calendar.getInstance()).getTime(), OrderKindEnum.COMMISSION.getKind());
        if (yesterdayAmount != null && !identityList.isEmpty()) {
            List<WelfareFlow> welfareFlowList = new ArrayList<>();
            List<UserCommission> userCommissionList = new ArrayList<>();

            String welfareRate = hipoConfigMapper.findValueByName(HipoConfigEnum.WELFARE_DAY_RATE.getConfig());
            BigDecimal eachAmount = yesterdayAmount.multiply(new BigDecimal(welfareRate)).divide(new BigDecimal(identityList.size()), 2, BigDecimal.ROUND_HALF_UP);

            identityList.stream().forEach(item -> {
                BigDecimal realRewardAmount = eachAmount;
                if (item.getWelfare().compareTo(eachAmount) < 0) {
                    realRewardAmount = item.getWelfare();
                }

                if (realRewardAmount.compareTo(BigDecimal.ZERO) > 0) {
                    identityMapper.updateWelfareAndUpdateAtById(item.getWelfare().subtract(realRewardAmount), new Date(), item.getId());

                    userCommissionList.add(buildRewardQueueIssued(item.getUserId(), HIPO_USER_ID, realRewardAmount,
                            UserCommissionTypeEnum.REWARD_WELFARE, yesterdayAmount, item.getType(), null, null, null));

                    welfareFlowList.add(WelfareFlow.builder()
                            .userId(item.getUserId())
                            .amount(realRewardAmount)
                            .tradeType(WelfareFlowTradeTypeEnum.REWARD_WELFARE.getTradeType())
                            .type(WelfareFlowTradeTypeEnum.REWARD_WELFARE.getType())
                            .point(item.getWelfare().subtract(realRewardAmount))
                            .createdAt(new Date())
                            .build());
                }
            });

            if (!welfareFlowList.isEmpty()) {
                welfareFlowMapper.batchInsert(welfareFlowList);
            }

            if (!userCommissionList.isEmpty()) {
                userCommissionMapper.batchInsert(userCommissionList);
            }
        }

    }

    private Calendar getFirstTime(Calendar calendar) {
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        return calendar;
    }
}